aboutsummaryrefslogtreecommitdiff
path: root/src/Font.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/Font.cc')
-rw-r--r--src/Font.cc255
1 files changed, 255 insertions, 0 deletions
diff --git a/src/Font.cc b/src/Font.cc
new file mode 100644
index 0000000..3d516dd
--- /dev/null
+++ b/src/Font.cc
@@ -0,0 +1,255 @@
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.1 2002/03/21 10:51:48 fluxgen Exp $
23#include "Font.hh"
24#include <cstdarg>
25#include <iostream> //for debug msg
26using namespace std;
27
28//use gnu extensions
29#ifndef _GNU_SOURCE
30#define _GNU_SOURCE
31#endif //_GNU_SOURCE
32
33#ifdef HAVE_CONFIG_H
34# include "../config.h"
35#endif // HAVE_CONFIG_H
36
37namespace FbTk
38{
39
40bool Font::m_multibyte = false; //TODO: fix multibyte
41
42Font::Font(Display *display, const char *name):m_loaded(false),
43m_display(display) {
44 m_font.fontstruct = 0;
45 m_font.set_extents = 0;
46 m_font.set = 0;
47 if (name!=0) {
48 load(name);
49 }
50
51}
52
53Font::~Font() {
54 freeFont();
55}
56
57bool Font::load(const char *name) {
58 if (m_multibyte) {
59 XFontSet set = createFontSet(m_display, name);
60 if (!set)
61 return false;
62 freeFont();
63
64 m_font.set = set;
65 m_font.set_extents = XExtentsOfFontSet(m_font.set);
66
67 } else {
68 XFontStruct *font = XLoadQueryFont(m_display, name);
69 if (font==0)
70 return false;
71 freeFont(); //free old font
72 m_font.fontstruct = font; //set new font
73 }
74
75 m_loaded = true; //mark the font loaded
76
77 return true;
78}
79
80bool Font::loadFromDatabase(XrmDatabase &database, const char *rname, const char *rclass) {
81 assert(rname);
82 assert(rclass);
83
84 XrmValue value;
85 char *value_type;
86
87 //this should probably be moved to a Database class so we can keep
88 //track of database init
89
90 if (XrmGetResource(database, rname, rclass, &value_type, &value)) {
91 #ifdef DEBUG
92 cerr<<__FILE__<<"("<<__LINE__<<"): Load font:"<<value.addr<<endl;
93 #endif
94 return load(value.addr);
95 }
96
97 return false;
98
99}
100unsigned int Font::getTextWidth(const char *text, unsigned int size) const {
101 if (text==0)
102 return 0;
103 if (multibyte()) {
104 XRectangle ink, logical;
105 XmbTextExtents(m_font.set, text, size,
106 &ink, &logical);
107 return logical.width;
108 } else {
109 assert(m_font.fontstruct);
110 return XTextWidth(m_font.fontstruct,
111 text, size);
112 }
113
114 return 0;
115}
116
117unsigned int Font::getHeight() const {
118 if (multibyte() && getFontSetExtents())
119 return getFontSetExtents()->max_ink_extent.height;
120 if (getFontStruct())
121 return getFontStruct()->ascent + getFontStruct()->descent;
122 return 0;
123}
124
125XFontSet Font::createFontSet(Display *display, const char *fontname) {
126 XFontSet fs;
127 const int FONT_ELEMENT_SIZE=50;
128 char **missing, *def = "-";
129 int nmissing, pixel_size = 0, buf_size = 0;
130 char weight[FONT_ELEMENT_SIZE], slant[FONT_ELEMENT_SIZE];
131
132 fs = XCreateFontSet(display,
133 fontname, &missing, &nmissing, &def);
134 if (fs && (! nmissing)) return fs;
135
136#ifdef HAVE_SETLOCALE
137 if (! fs) {
138 if (nmissing) XFreeStringList(missing);
139
140 setlocale(LC_CTYPE, "C");
141 fs = XCreateFontSet(m_display, fontname,
142 &missing, &nmissing, &def);
143 setlocale(LC_CTYPE, "");
144 }
145#endif // HAVE_SETLOCALE
146
147 if (fs) {
148 XFontStruct **fontstructs;
149 char **fontnames;
150 XFontsOfFontSet(fs, &fontstructs, &fontnames);
151 fontname = fontnames[0];
152 }
153
154 getFontElement(fontname, weight, FONT_ELEMENT_SIZE,
155 "-medium-", "-bold-", "-demibold-", "-regular-", NULL);
156 getFontElement(fontname, slant, FONT_ELEMENT_SIZE,
157 "-r-", "-i-", "-o-", "-ri-", "-ro-", NULL);
158 getFontSize(fontname, &pixel_size);
159
160 if (! strcmp(weight, "*"))
161 strncpy(weight, "medium", FONT_ELEMENT_SIZE);
162 if (! strcmp(slant, "*"))
163 strncpy(slant, "r", FONT_ELEMENT_SIZE);
164 if (pixel_size < 3)
165 pixel_size = 3;
166 else if (pixel_size > 97)
167 pixel_size = 97;
168
169 buf_size = strlen(fontname) + (FONT_ELEMENT_SIZE * 2) + 64;
170 char *pattern2 = new char[buf_size];
171 snprintf(pattern2, buf_size - 1,
172 "%s,"
173 "-*-*-%s-%s-*-*-%d-*-*-*-*-*-*-*,"
174 "-*-*-*-*-*-*-%d-*-*-*-*-*-*-*,*",
175 fontname, weight, slant, pixel_size, pixel_size);
176 fontname = pattern2;
177
178 if (nmissing)
179 XFreeStringList(missing);
180 if (fs)
181 XFreeFontSet(display, fs);
182
183 fs = XCreateFontSet(display, fontname,
184 &missing, &nmissing, &def);
185 delete [] pattern2;
186
187 return fs;
188}
189
190const char *Font::getFontElement(const char *pattern, char *buf, int bufsiz, ...) {
191 const char *p, *v;
192 char *p2;
193 va_list va;
194
195 va_start(va, bufsiz);
196 buf[bufsiz-1] = 0;
197 buf[bufsiz-2] = '*';
198 while((v = va_arg(va, char *)) != NULL) {
199 p = strcasestr(pattern, v);
200 if (p) {
201 strncpy(buf, p+1, bufsiz-2);
202 p2 = strchr(buf, '-');
203 if (p2) *p2=0;
204 va_end(va);
205 return p;
206 }
207 }
208 va_end(va);
209 strncpy(buf, "*", bufsiz);
210 return NULL;
211}
212
213const char *Font::getFontSize(const char *pattern, int *size) {
214 const char *p;
215 const char *p2=0;
216 int n=0;
217
218 for (p=pattern; 1; p++) {
219 if (!*p) {
220 if (p2!=NULL && n>1 && n<72) {
221 *size = n; return p2+1;
222 } else {
223 *size = 16; return NULL;
224 }
225 } else if (*p=='-') {
226 if (n>1 && n<72 && p2!=NULL) {
227 *size = n;
228 return p2+1;
229 }
230 p2=p; n=0;
231 } else if (*p>='0' && *p<='9' && p2!=NULL) {
232 n *= 10;
233 n += *p-'0';
234 } else {
235 p2=NULL; n=0;
236 }
237 }
238}
239
240void Font::freeFont() {
241 //free memory
242 if (m_font.fontstruct!=0)
243 XFreeFont(m_display, m_font.fontstruct);
244 if (m_font.set)
245 XFreeFontSet(m_display, m_font.set);
246
247 //clear struct
248 m_font.fontstruct = 0;
249 m_font.set = 0;
250 m_font.set_extents = 0;
251
252 m_loaded = false; //mark the font not loaded
253}
254
255};