aboutsummaryrefslogtreecommitdiff
path: root/src/Font.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/Font.cc')
-rw-r--r--src/Font.cc271
1 files changed, 71 insertions, 200 deletions
diff --git a/src/Font.cc b/src/Font.cc
index 5203ccb..627a825 100644
--- a/src/Font.cc
+++ b/src/Font.cc
@@ -19,10 +19,20 @@
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE. 20// DEALINGS IN THE SOFTWARE.
21 21
22//$Id: Font.cc,v 1.10 2002/09/03 12:05:01 fluxgen Exp $ 22//$Id: Font.cc,v 1.11 2002/10/13 22:27:21 fluxgen Exp $
23 23
24 24
25#include "Font.hh" 25#include "Font.hh"
26#include "FontImp.hh"
27
28// for antialias
29#ifdef USE_XFT
30#include "XftFontImp.hh"
31#endif // USE_XFT
32
33// standard font system
34#include "XFontImp.hh"
35#include "XmbFontImp.hh"
26 36
27#ifdef HAVE_CONFIG_H 37#ifdef HAVE_CONFIG_H
28#include "../config.h" 38#include "../config.h"
@@ -50,231 +60,92 @@
50 60
51#include "StringUtil.hh" 61#include "StringUtil.hh"
52 62
53namespace FbTk 63namespace FbTk {
54{
55 64
56bool Font::m_multibyte = false; //TODO: fix multibyte 65bool Font::m_multibyte = false;
66bool Font::m_utf8mode = false;
57 67
58Font::Font(Display *display, const char *name):m_loaded(false), 68Font::Font(const char *name, bool antialias) {
59m_display(display) {
60 m_font.fontstruct = 0;
61 m_font.set_extents = 0;
62 m_font.set = 0;
63 69
64 // MB_CUR_MAX returns the size of a char in the current locale 70 // MB_CUR_MAX returns the size of a char in the current locale
65 if (MB_CUR_MAX > 1) 71 if (MB_CUR_MAX > 1) // more than one byte, then we're multibyte
66 m_multibyte = true; 72 m_multibyte = true;
73
74 char *s; // temporary string for enviroment variable
75 // check for utf-8 mode
76 if (((s = getenv("LC_ALL")) && *s) ||
77 ((s = getenv("LC_CTYPE")) && *s) ||
78 ((s = getenv("LANG")) && *s)) {
79 if (strstr(s, "UTF-8"))
80 m_utf8mode = true;
81 }
82
83 // create the right font implementation
84#ifdef USE_XFT
85 if (antialias) {
86 m_fontimp = new XftFontImp();
87 }
88#endif //USE_XFT
89 // if we didn't create a Xft font then create basic font
90 if (m_fontimp.get() == 0) {
91 if (m_multibyte || m_utf8mode)
92 m_fontimp = std::auto_ptr<FontImp>(new XmbFontImp(0, m_utf8mode));
93 else // basic font implementation
94 m_fontimp = std::auto_ptr<FontImp>(new XFontImp(0));
95 }
67 96
68 if (name!=0) { 97 if (name != 0) {
69 load(name); 98 load(name);
70 } 99 }
71 100
72} 101}
73 102
74Font::~Font() { 103Font::~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 104
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} 105}
100 106
101bool Font::loadFromDatabase(XrmDatabase &database, const char *rname, const char *rclass) { 107void Font::setAntialias(bool flag) {
102 assert(rname);
103 assert(rclass);
104 108
105 XrmValue value; 109#ifdef USE_XFT
106 char *value_type; 110 bool is_antialias = typeid(m_fontimp) == typeid(XftFontImp);
107 111
108 //This should probably be moved to a Database class so we can keep 112 if (flag && !is_antialias) {
109 //track of database init 113 m_fontimp = std::auto_ptr<FontImp>(new XftFontImp(m_fontstr.c_str()));
110 114 } else if (!flag && is_antialias)
111 if (XrmGetResource(database, rname, rclass, &value_type, &value)) { 115#endif // USE_XFT
112 #ifdef DEBUG 116 {
113 std::cerr<<__FILE__<<"("<<__LINE__<<"): Load font:"<<value.addr<<std::endl; 117 if (m_multibyte || m_utf8mode)
114 #endif 118 m_fontimp = std::auto_ptr<FontImp>(new XmbFontImp(m_fontstr.c_str(), m_utf8mode));
115 return load(value.addr); 119 else
120 m_fontimp = std::auto_ptr<FontImp>(new XFontImp(m_fontstr.c_str()));
116 } 121 }
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} 122}
149 123
150XFontSet Font::createFontSet(Display *display, const char *fontname) { 124bool Font::load(const char *name) {
151 XFontSet fs; 125 if (name == 0)
152 const int FONT_ELEMENT_SIZE=50; 126 return false;
153 char **missing, *def = "-"; 127 bool ret_val = m_fontimp->load(name);
154 int nmissing, pixel_size = 0, buf_size = 0; 128 if (ret_val && name == 0) { //prevent from having a bad fontimp
155 char weight[FONT_ELEMENT_SIZE], slant[FONT_ELEMENT_SIZE]; 129 m_fontstr = name; // if the load really succeded then set font string
156 130 } else {
157 fs = XCreateFontSet(display, 131 m_fontstr = "";
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 } 132 }
178 133
179 getFontElement(fontname, weight, FONT_ELEMENT_SIZE, 134 return ret_val;
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} 135}
214 136
215const char *Font::getFontElement(const char *pattern, char *buf, int bufsiz, ...) { 137unsigned int Font::textWidth(const char *text, unsigned int size) const {
216 const char *p, *v; 138 return m_fontimp->textWidth(text, size);
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} 139}
237 140
238const char *Font::getFontSize(const char *pattern, int *size) { 141unsigned int Font::height() const {
239 const char *p; 142 return m_fontimp->height();
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} 143}
264 144
265void Font::freeFont() { 145void Font::drawText(Drawable w, int screen, GC gc, const char *text, size_t len, int x, int y) const {
266 //free memory 146 if (text == 0 || len == 0)
267 if (m_font.fontstruct!=0) 147 return;
268 XFreeFont(m_display, m_font.fontstruct); 148 m_fontimp->drawText(w, screen, gc, text, len, x, y);
269 if (m_font.set) 149}
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 150
280}; 151};