aboutsummaryrefslogtreecommitdiff
path: root/src/Font.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/Font.cc')
-rw-r--r--src/Font.cc280
1 files changed, 280 insertions, 0 deletions
diff --git a/src/Font.cc b/src/Font.cc
new file mode 100644
index 0000000..5203ccb
--- /dev/null
+++ b/src/Font.cc
@@ -0,0 +1,280 @@
1// Font.cc
2// Copyright (c) 2002 Henrik Kinnunen (fluxgen@linuxmail.org)
3//
4// Permission is hereby granted, free of charge, to any person obtaining a
5// copy of this software and associated documentation files (the "Software"),
6// to deal in the Software without restriction, including without limitation
7// the rights to use, copy, modify, merge, publish, distribute, sublicense,
8// and/or sell copies of the Software, and to permit persons to whom the
9// Software is furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included in
12// all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE.
21
22//$Id: Font.cc,v 1.10 2002/09/03 12:05:01 fluxgen Exp $
23
24
25#include "Font.hh"
26
27#ifdef HAVE_CONFIG_H
28#include "../config.h"
29#endif // HAVE_CONFIG_H
30
31//use gnu extensions
32#ifndef _GNU_SOURCE
33#define _GNU_SOURCE
34#endif //_GNU_SOURCE
35
36#ifndef __USE_GNU
37#define __USE_GNU
38#endif //__USE_GNU
39
40#include <cstdarg>
41#include <iostream>
42#include <cassert>
43#include <string>
44#include <cstdio>
45#include <string.h>
46
47#ifdef HAVE_SETLOCALE
48#include <locale.h>
49#endif //HAVE_SETLOCALE
50
51#include "StringUtil.hh"
52
53namespace FbTk
54{
55
56bool Font::m_multibyte = false; //TODO: fix multibyte
57
58Font::Font(Display *display, const char *name):m_loaded(false),
59m_display(display) {
60 m_font.fontstruct = 0;
61 m_font.set_extents = 0;
62 m_font.set = 0;
63
64 // MB_CUR_MAX returns the size of a char in the current locale
65 if (MB_CUR_MAX > 1)
66 m_multibyte = true;
67
68 if (name!=0) {
69 load(name);
70 }
71
72}
73
74Font::~Font() {
75 freeFont();
76}
77
78bool Font::load(const char *name) {
79 if (m_multibyte) {
80 XFontSet set = createFontSet(m_display, name);
81 if (!set)
82 return false;
83 freeFont();
84
85 m_font.set = set;
86 m_font.set_extents = XExtentsOfFontSet(m_font.set);
87
88 } else {
89 XFontStruct *font = XLoadQueryFont(m_display, name);
90 if (font==0)
91 return false;
92 freeFont(); //free old font
93 m_font.fontstruct = font; //set new font
94 }
95
96 m_loaded = true; //mark the font loaded
97
98 return true;
99}
100
101bool Font::loadFromDatabase(XrmDatabase &database, const char *rname, const char *rclass) {
102 assert(rname);
103 assert(rclass);
104
105 XrmValue value;
106 char *value_type;
107
108 //This should probably be moved to a Database class so we can keep
109 //track of database init
110
111 if (XrmGetResource(database, rname, rclass, &value_type, &value)) {
112 #ifdef DEBUG
113 std::cerr<<__FILE__<<"("<<__LINE__<<"): Load font:"<<value.addr<<std::endl;
114 #endif
115 return load(value.addr);
116 }
117
118 return false;
119
120}
121unsigned int Font::textWidth(const char *text, unsigned int size) const {
122 if (text==0)
123 return 0;
124 if (multibyte()) {
125 XRectangle ink, logical;
126 XmbTextExtents(m_font.set, text, size,
127 &ink, &logical);
128 return logical.width;
129 } else {
130 assert(m_font.fontstruct);
131 return XTextWidth(m_font.fontstruct,
132 text, size);
133 }
134
135 return 0;
136}
137
138unsigned int Font::height() const {
139 if (!isLoaded())
140 return 0;
141
142 if (multibyte() && fontSetExtents())
143 return fontSetExtents()->max_ink_extent.height;
144 if (fontStruct())
145 return fontStruct()->ascent + fontStruct()->descent;
146
147 return 0;
148}
149
150XFontSet Font::createFontSet(Display *display, const char *fontname) {
151 XFontSet fs;
152 const int FONT_ELEMENT_SIZE=50;
153 char **missing, *def = "-";
154 int nmissing, pixel_size = 0, buf_size = 0;
155 char weight[FONT_ELEMENT_SIZE], slant[FONT_ELEMENT_SIZE];
156
157 fs = XCreateFontSet(display,
158 fontname, &missing, &nmissing, &def);
159 if (fs && (! nmissing)) return fs;
160
161#ifdef HAVE_SETLOCALE
162 if (! fs) {
163 if (nmissing) XFreeStringList(missing);
164
165 setlocale(LC_CTYPE, "C");
166 fs = XCreateFontSet(display, fontname,
167 &missing, &nmissing, &def);
168 setlocale(LC_CTYPE, "");
169 }
170#endif // HAVE_SETLOCALE
171
172 if (fs) {
173 XFontStruct **fontstructs;
174 char **fontnames;
175 XFontsOfFontSet(fs, &fontstructs, &fontnames);
176 fontname = fontnames[0];
177 }
178
179 getFontElement(fontname, weight, FONT_ELEMENT_SIZE,
180 "-medium-", "-bold-", "-demibold-", "-regular-", 0);
181 getFontElement(fontname, slant, FONT_ELEMENT_SIZE,
182 "-r-", "-i-", "-o-", "-ri-", "-ro-", 0);
183 getFontSize(fontname, &pixel_size);
184
185 if (! strcmp(weight, "*"))
186 std::strncpy(weight, "medium", FONT_ELEMENT_SIZE);
187 if (! strcmp(slant, "*"))
188 std::strncpy(slant, "r", FONT_ELEMENT_SIZE);
189 if (pixel_size < 3)
190 pixel_size = 3;
191 else if (pixel_size > 97)
192 pixel_size = 97;
193
194 buf_size = strlen(fontname) + (FONT_ELEMENT_SIZE * 2) + 64;
195 char *pattern2 = new char[buf_size];
196 snprintf(pattern2, buf_size - 1,
197 "%s,"
198 "-*-*-%s-%s-*-*-%d-*-*-*-*-*-*-*,"
199 "-*-*-*-*-*-*-%d-*-*-*-*-*-*-*,*",
200 fontname, weight, slant, pixel_size, pixel_size);
201 fontname = pattern2;
202
203 if (nmissing)
204 XFreeStringList(missing);
205 if (fs)
206 XFreeFontSet(display, fs);
207
208 fs = XCreateFontSet(display, fontname,
209 &missing, &nmissing, &def);
210 delete [] pattern2;
211
212 return fs;
213}
214
215const char *Font::getFontElement(const char *pattern, char *buf, int bufsiz, ...) {
216 const char *p, *v;
217 char *p2;
218 va_list va;
219
220 va_start(va, bufsiz);
221 buf[bufsiz-1] = 0;
222 buf[bufsiz-2] = '*';
223 while((v = va_arg(va, char *)) != 0) {
224 p = StringUtil::strcasestr(pattern, v);
225 if (p) {
226 std::strncpy(buf, p+1, bufsiz-2);
227 p2 = strchr(buf, '-');
228 if (p2) *p2=0;
229 va_end(va);
230 return p;
231 }
232 }
233 va_end(va);
234 std::strncpy(buf, "*", bufsiz);
235 return 0;
236}
237
238const char *Font::getFontSize(const char *pattern, int *size) {
239 const char *p;
240 const char *p2=0;
241 int n=0;
242
243 for (p=pattern; 1; p++) {
244 if (!*p) {
245 if (p2!=0 && n>1 && n<72) {
246 *size = n; return p2+1;
247 } else {
248 *size = 16; return 0;
249 }
250 } else if (*p=='-') {
251 if (n>1 && n<72 && p2!=0) {
252 *size = n;
253 return p2+1;
254 }
255 p2=p; n=0;
256 } else if (*p>='0' && *p<='9' && p2!=0) {
257 n *= 10;
258 n += *p-'0';
259 } else {
260 p2=0; n=0;
261 }
262 }
263}
264
265void Font::freeFont() {
266 //free memory
267 if (m_font.fontstruct!=0)
268 XFreeFont(m_display, m_font.fontstruct);
269 if (m_font.set)
270 XFreeFontSet(m_display, m_font.set);
271
272 //clear struct
273 m_font.fontstruct = 0;
274 m_font.set = 0;
275 m_font.set_extents = 0;
276
277 m_loaded = false; //mark the font not loaded
278}
279
280};