ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/defaultfont.C
(Generate patch)

Comparing rxvt-unicode/src/defaultfont.C (file contents):
Revision 1.6 by pcg, Wed Dec 17 22:29:03 2003 UTC vs.
Revision 1.42 by pcg, Mon Mar 15 06:13:35 2004 UTC

1/*--------------------------------*-C-*---------------------------------*; 1/*--------------------------------*-C-*---------------------------------*;
2 * File: defaultfont.C 2 * File: defaultfont.C
3 *----------------------------------------------------------------------* 3 *----------------------------------------------------------------------*
4 * Copyright (c) 2003 Marc Lehmann rxvt@plan9.de> 4 * Copyright (c) 2003-2004 Marc Lehmann <pcg@goof.com>
5 * - original version. 5 * - original version.
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or 9 * the Free Software Foundation; either version 2 of the License, or
21 21
22#include "../config.h" 22#include "../config.h"
23#include "rxvt.h" 23#include "rxvt.h"
24#include "defaultfont.h" 24#include "defaultfont.h"
25 25
26#include <cstdlib>
27
26#define DISPLAY r->Xdisplay 28#define DISPLAY r->display->display
27#define DRAWABLE r->TermWin.vt
28#define GC r->TermWin.gc 29#define GC r->TermWin.gc
29 30
30const struct rxvt_fallback_font { 31const struct rxvt_fallback_font {
31 codeset cs; 32 codeset cs;
32 const char *name; 33 const char *name;
57 58
58 // japanese 59 // japanese
59#if ENCODING_JP || ENCODING_JP_EXT 60#if ENCODING_JP || ENCODING_JP_EXT
60# if XFT 61# if XFT
61 // prefer xft for complex scripts 62 // prefer xft for complex scripts
62 { CS_UNICODE, "xft:Kochi Gothic" }, 63 { CS_UNICODE, "xft:Kochi Gothic:antialias=false" },
63# endif 64# endif
64 { CS_JIS0201_1976_0, "-*-mincho-*-r-*--*-*-*-*-c-*-jisx0201*-0" }, 65 { CS_JIS0201_1976_0, "-*-mincho-*-r-*--*-*-*-*-c-*-jisx0201*-0" },
65 { CS_JIS0208_1983_0, "-*-mincho-*-r-*--*-*-*-*-c-*-jisx0208*-0" }, 66 { CS_JIS0208_1990_0, "-*-mincho-*-r-*--*-*-*-*-c-*-jisx0208*-0" },
66 { CS_JIS0212_1990_0, "-*-mincho-*-r-*--*-*-*-*-c-*-jisx0212*-0" }, 67 { CS_JIS0212_1990_0, "-*-mincho-*-r-*--*-*-*-*-c-*-jisx0212*-0" },
67#endif 68#endif
68 69
69#if ENCODING_CN || ENCODING_CN_EXT 70#if ENCODING_CN || ENCODING_CN_EXT
70# if XFT 71# if XFT
71 { CS_BIG5_EXT, "xft:AR PL Mingti2L Big5" }, 72 { CS_BIG5_EXT, "xft:AR PL Mingti2L Big5" },
72 { CS_BIG5_EXT, "xft:AR PL KaitiM Big5" }, 73 { CS_BIG5_EXT, "xft:AR PL KaitiM Big5" },
73 { CS_GB2312_1980_0, "xft:AR PL KaitiM GB" }, 74 { CS_GB2312_1980_0, "xft:AR PL KaitiM GB" },
74 { CS_GB2312_1980_0, "xft:AR PL SungtiL GB" }, 75 { CS_GB2312_1980_0, "xft:AR PL SungtiL GB" },
75# endif 76# endif
77 { CS_BIG5, "-*-*-*-*-*-*-*-*-*-*-c-*-big5-0" },
78 { CS_BIG5_PLUS, "-*-*-*-*-*-*-*-*-*-*-c-*-big5p-0" },
79 { CS_BIG5_EXT, "-*-*-*-*-*-*-*-*-*-*-c-*-big5.eten-0" },
80 { CS_CNS11643_1992_1, "-*-*-*-*-*-*-*-*-*-*-c-*-gb2312*-0" },
76 { CS_CNS11643_1992_1, "-*-*-*-r-*-*-*-*-*-*-c-*-cns11643.1992-1" }, 81 { CS_CNS11643_1992_1, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-1" },
77 { CS_CNS11643_1992_2, "-*-*-*-r-*-*-*-*-*-*-c-*-cns11643.1992-2" }, 82 { CS_CNS11643_1992_2, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-2" },
78 { CS_CNS11643_1992_3, "-*-*-*-r-*-*-*-*-*-*-c-*-cns11643.1992-3" }, 83 { CS_CNS11643_1992_3, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-3" },
79 { CS_CNS11643_1992_4, "-*-*-*-r-*-*-*-*-*-*-c-*-cns11643.1992-4" }, 84 { CS_CNS11643_1992_4, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-4" },
80 { CS_CNS11643_1992_5, "-*-*-*-r-*-*-*-*-*-*-c-*-cns11643.1992-5" }, 85 { CS_CNS11643_1992_5, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-5" },
81 { CS_CNS11643_1992_6, "-*-*-*-r-*-*-*-*-*-*-c-*-cns11643.1992-6" }, 86 { CS_CNS11643_1992_6, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-6" },
82 { CS_CNS11643_1992_7, "-*-*-*-r-*-*-*-*-*-*-c-*-cns11643.1992-7" }, 87 { CS_CNS11643_1992_7, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-7" },
83 { CS_CNS11643_1992_F, "-*-*-*-r-*-*-*-*-*-*-c-*-cns11643.1992-f" }, 88 { CS_CNS11643_1992_F, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-f" },
84#endif 89#endif
85 90
86#if XFT 91#if XFT
87 { CS_UNICODE, "xft:Andale Mono" }, 92 { CS_UNICODE, "xft:Andale Mono" },
88 { CS_UNICODE, "xft:Arial Unicode MS" }, 93 { CS_UNICODE, "xft:Arial Unicode MS" },
89#endif 94#endif
90 { CS_UNICODE, "-*-lucidatypewriter-*-r-*-*-*-*-*-*-m-*-iso10646-1" }, 95 { CS_UNICODE, "-*-lucidatypewriter-*-*-*-*-*-*-*-*-m-*-iso10646-1" },
96 { CS_UNICODE, "xft:FreeMono" },
97 { CS_UNICODE, "-*-unifont-*-*-*-*-*-*-*-*-c-*-iso10646-1" },
98 { CS_UNICODE, "-*-*-*-r-*-*-*-*-*-*-c-*-iso10646-1" },
91 { CS_UNICODE, "-*-*-*-r-*-*-*-*-*-*-m-*-iso10646-1" }, 99 { CS_UNICODE, "-*-*-*-r-*-*-*-*-*-*-m-*-iso10646-1" },
92 { CS_UNICODE, "-*-*-*-r-*-*-*-*-*-*-m-*-iso10646-1" }, 100
93 { CS_UNICODE, "-*-*-*-r-*-*-*-*-*-*-m-*-iso10646-1" }, 101#if UNICODE_3 && XFT
102 { CS_UNICODE, "xft:Code2001" }, // contains many plane-1 characters
103#endif
94 104
95 { CS_UNKNOWN, 0 } 105 { CS_UNKNOWN, 0 }
96}; 106};
97 107
98///////////////////////////////////////////////////////////////////////////// 108/////////////////////////////////////////////////////////////////////////////
99 109
110#if XFT
111rxvt_drawable::~rxvt_drawable ()
112{
113 if (xftdrawable)
114 XftDrawDestroy (xftdrawable);
115}
116
117rxvt_drawable::operator XftDraw *()
118{
119 if (!xftdrawable)
120 xftdrawable = XftDrawCreate (display->display, drawable, display->visual, display->cmap);
121
122 return xftdrawable;
123}
124#endif
125
126/////////////////////////////////////////////////////////////////////////////
127
100static void *enc_buf; 128static void *enc_buf;
101static uint32_t enc_len; 129static uint32_t enc_len;
102 130
103static inline void * 131static inline void *
104get_enc_buf (int len) 132get_enc_buf (uint32_t len)
105{ 133{
106 if (len > enc_len) 134 if (len > enc_len)
107 { 135 {
108 free (enc_buf); 136 free (enc_buf);
109 enc_buf = malloc (len); 137 enc_buf = malloc (len);
111 139
112 return enc_buf; 140 return enc_buf;
113} 141}
114 142
115static const char * 143static const char *
116enc_char (const text_t *text, int len, codeset cs, bool &zero) 144enc_char (const text_t *text, uint32_t len, codeset cs, bool &zero)
117{ 145{
118 uint8_t *buf = (uint8_t *)get_enc_buf (len); 146 uint8_t *buf = (uint8_t *)get_enc_buf (len);
119 147
120 while (len--) 148 while (len--)
121 { 149 {
132 160
133 return (const char *)enc_buf; 161 return (const char *)enc_buf;
134} 162}
135 163
136static const XChar2b * 164static const XChar2b *
137enc_xchar2b (const text_t *text, int len, codeset cs, bool &zero) 165enc_xchar2b (const text_t *text, uint32_t len, codeset cs, bool &zero)
138{ 166{
139 XChar2b *buf = (XChar2b *)get_enc_buf (len * sizeof (XChar2b)); 167 XChar2b *buf = (XChar2b *)get_enc_buf (len * sizeof (XChar2b));
140 168
141 while (len--) 169 while (len--)
142 { 170 {
157} 185}
158 186
159///////////////////////////////////////////////////////////////////////////// 187/////////////////////////////////////////////////////////////////////////////
160 188
161void 189void
162rxvt_font::clear_rect (int x, int y, int w, int h, int color) 190rxvt_font::clear_rect (rxvt_drawable &d, int x, int y, int w, int h, int color)
163{ 191{
164 if (color == Color_bg) 192 if (color == Color_bg)
165 XClearArea (DISPLAY, DRAWABLE, x, y, w, h, FALSE); 193 XClearArea (d.display->display, d, x, y, w, h, FALSE);
166 else if (color >= 0) 194 else if (color >= 0)
167 { 195 {
196#if XFT
197 XftDrawRect (d, &r->PixColors[color].c, x, y, w, h);
198#else
168 XSetForeground (DISPLAY, GC, r->PixColors[color]); 199 XSetForeground (d.display->display, GC, r->PixColors[color]);
169 XFillRectangle (DISPLAY, DRAWABLE, GC, x, y, w, h); 200 XFillRectangle (d.display->display, d, GC, x, y, w, h);
201#endif
170 } 202 }
171} 203}
172 204
173static const char *linedraw_cmds[128] = { 205static const char *linedraw_cmds[128] = {
174 "1hH", "2hH", "1vV", "2vV", 206 "1-", "2-", "1|", "2|",
175 0, 0, 0, 0, 207 0, 0, 0, 0,
176 0, 0, 0, 0, 208 0, 0, 0, 0,
177 "1HV", "2H1V", "1H2V", "2HV", 209 "1HV", "2H1V", "1H2V", "2HV",
178 210
179 // 2510 211 // 2510
180 "1hV", "2h1V", "1h2V", "2hV", 212 "1hV", "2h1V", "1h2V", "2hV",
181 "1Hv", "2H1v", "1H2v", "2Hv", 213 "1Hv", "2H1v", "1H2v", "2Hv",
182 "1hv", "2h1v", "1h2v", "2hv", 214 "1hv", "2h1v", "1h2v", "2hv",
183 "1HvV", "2H1vV", "1HV2v", "1Hv2V", 215 "1H|", "2H1|", "1HV2v", "1Hv2V",
184 216
185 // 2520 217 // 2520
186 "1H2vV", "2Hv1V", "2HV1v", "2HvV", 218 "1H2|", "2Hv1V", "2HV1v", "2H|",
187 "1hvV", "2h1vV", "1hV2v", "1hv2V", 219 "1h|", "2h1|", "1hV2v", "1hv2V",
188 "1h2vV", "2hv1V", "1v2hV", "2hvV", 220 "1h2|", "2hv1V", "1v2hV", "2h|",
189 "1hHV", "2h1HV", "2H1hV", "2hH1V", 221 "1-V", "2h1HV", "2H1hV", "2-1V",
190 222
191 // 2530 223 // 2530
192 "1hH2V", "2hV1H", "1h2HV", "2hHV", 224 "1-2V", "2hV1H", "1h2HV", "2-V",
193 "1hHv", "1vH2h", "1hv2H", "1v2hH", 225 "1-v", "1vH2h", "1hv2H", "1v2-",
194 "1hH2v", "1H2hv", "1h2Hv", "2hHv", 226 "1-2v", "1H2hv", "1h2Hv", "2-v",
195 "1hHvV", "1vVH2h", "1hvV2H", "1vV2hH", 227 "1-|", "1|H2h", "1h|2H", "1|2-",
196 228
197 // 2540 229 // 2540
198 "1hHV2v", "1hHv2V", "1hH2vV", "1HV2hv", 230 "1-V2v", "1-v2V", "1-2|", "1HV2hv",
199 "1hV2Hv", "1Hv2hV", "1hv2HV", "1V2hHv", 231 "1hV2Hv", "1Hv2hV", "1hv2HV", "1V2-v",
200 "1v2hHV", "1H2hvV", "1h2HvV", "2hHvV", 232 "1v2-V", "1H2h|", "1h2H|", "2-|",
201 0, 0, 0, 0, 233 0, 0, 0, 0,
202 234
203 // 2550 235 // 2550
204 0, 0, 0, 0, 236 0, 0, 0, 0,
205 0, 0, 0, 0, 237 0, 0, 0, 0,
208 240
209 // 2560 241 // 2560
210 0, 0, 0, 0, 242 0, 0, 0, 0,
211 0, 0, 0, 0, 243 0, 0, 0, 0,
212 0, 0, 0, 0, 244 0, 0, 0, 0,
213 0, 0, 0, 0, 245 0, "A", "B", "C",
214 246
215 // 2570 247 // 2570
216 0, "1a", "1b", "1ab", 248 "D", "1/", "1\\", "1/\\",
217 "1h", "1v", "1H", "1V", 249 "1h", "1v", "1H", "1V",
218 "2h", "2v", "2H", "2V", 250 "2h", "2v", "2H", "2V",
219 "1h2H", "1v2V", "1H2h", "1V2v" 251 "1h2H", "1v2V", "1H2h", "1V2v"
220 252
221 // to be done 253 // to be done
222}; 254};
223 255
224struct rxvt_font_default : rxvt_font { 256struct rxvt_font_default : rxvt_font {
225 bool load (int maxheight) 257 rxvt_fontprop properties ()
258 {
259 rxvt_fontprop p;
260
261 p.width = p.height = 1;
262 p.weight = rxvt_fontprop::medium;
263 p.slant = rxvt_fontprop::roman;
264
265 return p;
266 }
267
268 bool load (const rxvt_fontprop &prop)
226 { 269 {
227 width = 1; height = 1; 270 width = 1; height = 1;
228 ascent = 1; descent = 0; 271 ascent = 1; descent = 0;
229 272
273 set_name ("built-in pseudofont");
274
230 return true; 275 return true;
231 } 276 }
232 277
233 bool has_codepoint (uint32_t unicode) 278 bool has_codepoint (unicode_t unicode)
234 { 279 {
235 if (unicode <= 0x001f) 280 if (unicode <= 0x001f)
236 return true; 281 return true;
282
237 if (unicode >= 0x0080 && unicode <= 0x009f) 283 if (unicode >= 0x0080 && unicode <= 0x009f)
238 return true; 284 return true;
239 285
240 if (unicode >= 0x2500 && unicode <= 0x257f 286 if (unicode >= 0x2500 && unicode <= 0x257f
241 && linedraw_cmds[unicode - 0x2500]) 287 && linedraw_cmds[unicode - 0x2500])
288 return true;
289
290 if (IS_COMPOSE (unicode))
242 return true; 291 return true;
243 292
244 switch (unicode) 293 switch (unicode)
245 { 294 {
246 case ZERO_WIDTH_CHAR: 295 case ZERO_WIDTH_CHAR:
248 } 297 }
249 298
250 return false; 299 return false;
251 } 300 }
252 301
253 void draw (int x, int y, 302 void draw (rxvt_drawable &d, int x, int y,
254 const text_t *text, int len, 303 const text_t *text, int len,
255 int fg, int bg); 304 int fg, int bg);
256}; 305};
257 306
258void 307void
259rxvt_font_default::draw (int x, int y, 308rxvt_font_default::draw (rxvt_drawable &d, int x, int y,
260 const text_t *text, int len, 309 const text_t *text, int len,
261 int fg, int bg) 310 int fg, int bg)
262{ 311{
263 clear_rect (x, y, r->TermWin.fwidth * len, r->TermWin.fheight, bg); 312 clear_rect (d, x, y, r->TermWin.fwidth * len, r->TermWin.fheight, bg);
264 313
265 XSetForeground (DISPLAY, GC, r->PixColors[fg]); 314 XSetForeground (d.display->display, GC, r->PixColors[fg]);
266 315
267 while (len--) 316 while (len--)
268 { 317 {
318#if ENABLE_COMBINING
319 compose_char *cc;
320#endif
269 text_t t = *text++; 321 text_t t = *text++;
270 322
323 // is it in our linedrawing table?
271 if (t >= 0x2500 & t <= 0x2580 && linedraw_cmds[t - 0x2500]) 324 if (t >= 0x2500 & t <= 0x2580 && linedraw_cmds[t - 0x2500])
272 { 325 {
273 const char *p = linedraw_cmds[t - 0x2500]; 326 const char *p = linedraw_cmds[t - 0x2500];
274 327
275 int x0 = x, x1 = x + r->TermWin.fwidth / 2, x2 = x + r->TermWin.fwidth ; 328 int W = r->TermWin.fwidth , w = (W - 1) / 2;
329 int H = r->TermWin.fheight, h = (H - 1) / 2;
330 int x0 = x, x1 = x + w, x2 = x + r->TermWin.fwidth ;
276 int y0 = y, y1 = y + r->TermWin.fheight / 2, y2 = y + r->TermWin.fheight; 331 int y0 = y, y1 = y + h, y2 = y + r->TermWin.fheight;
277 332
278 XGCValues gcv; 333 XGCValues gcv;
334
335 gcv.cap_style = CapNotLast;
336 XChangeGC (d.display->display, GC, GCCapStyle, &gcv);
279 337
280 while (*p) 338 while (*p)
281 { 339 {
282 switch (*p++) 340 switch (*p++)
283 { 341 {
284 case '1': 342 case '1':
285 gcv.line_width = 0; 343 gcv.line_width = 0;
286 XChangeGC (DISPLAY, GC, GCLineWidth, &gcv); 344 XChangeGC (d.display->display, GC, GCLineWidth, &gcv);
287 break; 345 break;
288 346
289 case '2': 347 case '2':
290 gcv.line_width = 2; 348 gcv.line_width = 3;
291 XChangeGC (DISPLAY, GC, GCLineWidth, &gcv); 349 XChangeGC (d.display->display, GC, GCLineWidth, &gcv);
292 break; 350 break;
293 351
294 case 'h': XDrawLine (DISPLAY, DRAWABLE, GC, x0, y1, x1, y1); break; 352 case 'h': XDrawLine (d.display->display, d, GC, x0, y1, x1+1, y1 ); break;
295 case 'H': XDrawLine (DISPLAY, DRAWABLE, GC, x1, y1, x2, y1); break; 353 case 'H': XDrawLine (d.display->display, d, GC, x2, y1, x1-1, y1 ); break;
354 case '-': XDrawLine (d.display->display, d, GC, x0, y1, x2 , y1 ); break;
296 case 'v': XDrawLine (DISPLAY, DRAWABLE, GC, x1, y0, x1, y1); break; 355 case 'v': XDrawLine (d.display->display, d, GC, x1, y0, x1 , y1+1); break;
356 case 'V': XDrawLine (d.display->display, d, GC, x1, y2, x1 , y1-1); break;
297 case 'V': XDrawLine (DISPLAY, DRAWABLE, GC, x1, y1, x1, y2); break; 357 case '|': XDrawLine (d.display->display, d, GC, x1, y0, x1 , y2 ); break;
358
298 case 'a': XDrawLine (DISPLAY, DRAWABLE, GC, x0, y2, x2, y0); break; 359 case '/' : XDrawLine (d.display->display, d, GC, x0, y2, x2 , y0 ); break;
299 case 'b': XDrawLine (DISPLAY, DRAWABLE, GC, x0, y0, x2, y2); break; 360 case '\\': XDrawLine (d.display->display, d, GC, x0, y0, x2 , y2 ); break;
361
362 case 'A': XDrawArc (d.display->display, d, GC, x1 , y1 , W-1, H-1, 90*64, 90*64); break;
363 case 'B': XDrawArc (d.display->display, d, GC, x1-W+1, y1 , W-1, H-1, 0*64, 90*64); break;
364 case 'C': XDrawArc (d.display->display, d, GC, x1-W+1, y1-H+1, W-1, H-1, 0*64, -90*64); break;
365 case 'D': XDrawArc (d.display->display, d, GC, x1 , y1-H+1, W-1, H-1, -90*64, -90*64); break;
300 } 366 }
301 } 367 }
302 368
303 gcv.line_width = 0; 369 gcv.line_width = 0;
304 XChangeGC (DISPLAY, GC, GCLineWidth, &gcv); 370 XChangeGC (d.display->display, GC, GCLineWidth, &gcv);
371 }
372
373#if ENABLE_COMBINING
374 else if (IS_COMPOSE (t) && (cc = rxvt_composite[t]))
305 } 375 {
376 rxvt_font *f1 = (*fs)[fs->find_font (cc->c1)];
377 f1->draw (d, x, y, &(t = cc->c1), 1, fg, bg);
378 if (cc->c2 != NOCHAR)
379 {
380 // prefer font of first character, for no good reasons
381 rxvt_font *f2 = f1->has_codepoint (cc->c2)
382 ? f1
383 : (*fs)[fs->find_font (cc->c2)];
384
385 f2->draw (d, x, y, &(t = cc->c2), 1, fg, -1);
386 }
387 }
388#endif
306 else 389 else
307 switch (*text++) 390 switch (t)
308 { 391 {
309 case NOCHAR:
310 case ZERO_WIDTH_CHAR: 392 case ZERO_WIDTH_CHAR:
311 break; 393 break;
312 default: 394 default:
313 XDrawRectangle (DISPLAY, DRAWABLE, GC, x + 2, y + 2, r->TermWin.fwidth - 5, r->TermWin.fheight - 5); 395 int w = 0;
396 while (len > 0 && *text == NOCHAR)
397 {
398 ++text;
399 --len;
400 w += r->TermWin.fwidth;
401 }
402
403 XDrawRectangle (d.display->display, d, GC, x + 2, y + 2,
404 w + r->TermWin.fwidth - 5, r->TermWin.fheight - 5);
405 x += w;
314 } 406 }
315 407
316 x += r->TermWin.fwidth; 408 x += r->TermWin.fwidth;
317 } 409 }
318} 410}
322struct rxvt_font_x11 : rxvt_font { 414struct rxvt_font_x11 : rxvt_font {
323 rxvt_font_x11 () { f = 0; } 415 rxvt_font_x11 () { f = 0; }
324 416
325 void clear (); 417 void clear ();
326 418
327 bool load (int maxheight); 419 rxvt_fontprop properties ();
328 420
421 bool load (const rxvt_fontprop &prop);
422
329 bool has_codepoint (uint32_t unicode); 423 bool has_codepoint (unicode_t unicode);
330 424
331 void draw (int x, int y, 425 void draw (rxvt_drawable &d, int x, int y,
332 const text_t *text, int len, 426 const text_t *text, int len,
333 int fg, int bg); 427 int fg, int bg);
334 428
335 XFontStruct *f; 429 XFontStruct *f;
336 codeset cs; 430 codeset cs;
337 bool enc2b, encm; 431 bool enc2b, encm;
338 432
339 const char *get_property (const char *property, const char *repl) const; 433 const char *get_property (XFontStruct *f, const char *property, const char *repl) const;
434 bool set_properties (rxvt_fontprop &p, int height, const char *weight, const char *slant, int avgwidth);
435 bool set_properties (rxvt_fontprop &p, XFontStruct *f);
436 bool set_properties (rxvt_fontprop &p, const char *name);
340}; 437};
341 438
342const char * 439const char *
343rxvt_font_x11::get_property (const char *property, const char *repl) const 440rxvt_font_x11::get_property (XFontStruct *f, const char *property, const char *repl) const
344{ 441{
345 unsigned long value; 442 unsigned long value;
346 443
347 if (XGetFontProperty (f, XInternAtom (DISPLAY, property, 0), &value)) 444 if (XGetFontProperty (f, XInternAtom (DISPLAY, property, 0), &value))
348 return XGetAtomName (DISPLAY, value); 445 return XGetAtomName (DISPLAY, value);
349 else 446 else
350 return repl; 447 return repl;
351} 448}
352 449
450rxvt_fontprop
451rxvt_font_x11::properties ()
452{
453 rxvt_fontprop p;
454 set_properties (p, f);
455 return p;
456}
457
353bool 458bool
354rxvt_font_x11::load (int maxheight) 459rxvt_font_x11::set_properties (rxvt_fontprop &p, int height, const char *weight, const char *slant, int avgwidth)
460{
461 p.width = avgwidth ? (avgwidth + 1) / 10 : (height + 1) / 2;
462 p.height = height;
463 p.weight = *weight == 'B' || *weight == 'b' ? rxvt_fontprop::bold : rxvt_fontprop::medium;
464 p.slant = *slant == 'r' || *slant == 'R' ? rxvt_fontprop::roman : rxvt_fontprop::italic;
465
466 return true;
467}
468
469bool
470rxvt_font_x11::set_properties (rxvt_fontprop &p, XFontStruct *f)
471{
472 const char *weight = get_property (f, "WEIGHT_NAME", "medium");
473 const char *slant = get_property (f, "SLANT", "r");
474
475 unsigned long height;
476 if (!XGetFontProperty (f, XInternAtom (DISPLAY, "PIXEL_SIZE", 0), &height))
477 return false;
478
479 unsigned long avgwidth;
480 if (!XGetFontProperty (f, XInternAtom (DISPLAY, "AVERAGE_WIDTH", 0), &avgwidth))
481 avgwidth = 0;
482
483 return set_properties (p, height, weight, slant, avgwidth);
484}
485
486bool
487rxvt_font_x11::set_properties (rxvt_fontprop &p, const char *name)
488{
489 int slashes = 0;
490 const char *comp[13];
491
492 for (const char *c = name; *c; c++)
493 if (*c == '-')
494 {
495 comp[slashes++] = c + 1;
496 if (slashes >= 13)
497 break;
498 }
499
500 /* can we short-circuit the costly XLoadQueryFont? */
501 if (slashes >= 13
502 && (*comp[ 6] >= '1' && *comp[ 6] <= '9')
503 && (*comp[11] >= '0' && *comp[11] <= '9'))
504 return set_properties (p, atoi (comp[6]), comp[2], comp[3], atoi (comp[11]));
505
506 XFontStruct *f = XLoadQueryFont (DISPLAY, name);
507
508 if (f)
509 {
510 // the font should really exist now. if not, we have a problem
511 // (e.g. if the user did xset fp rehash just when we were searching fonts).
512 // in that case, just return garbage.
513 bool ret = set_properties (p, f);
514 XFreeFont (DISPLAY, f);
515 return ret;
516 }
517 else
518 return false;
519}
520
521// fix the size of scalable fonts
522static void
523fix_scalable (char *buf, const char *name, const rxvt_fontprop &prop)
524{
525 int slashes = 0;
526 const char *size;
527
528 for (const char *c = name; *c; c++)
529 if (*c == '-')
530 {
531 if (slashes == 6)
532 size = c + 1;
533
534 if (++slashes >= 13)
535 break;
536 }
537
538 if (slashes >= 13 && size[0] == '0')
539 {
540 strncpy (buf, name, size - name);
541 buf += size - name;
542 buf += sprintf (buf, "%d", prop.height);
543 strcpy (buf, size + 1);
544 }
545 else
546 strcpy (buf, name);
547}
548
549bool
550rxvt_font_x11::load (const rxvt_fontprop &prop)
355{ 551{
356 clear (); 552 clear ();
357 553
358 char **list; 554 char **list;
359 int count; 555 int count;
360 XFontStruct *info;
361 list = XListFontsWithInfo (DISPLAY, name, 128, &count, &info); 556 list = XListFonts (DISPLAY, name, 512, &count);
557 set_name (0);
362 558
363 if (!list) 559 if (!list)
364 return false; 560 return false;
365 561
366 XFontStruct *best = 0; 562 int bestdiff = 0x7fffffff;
367 for (int i = 0; i < count; i++) 563 for (int i = 0; i < count; i++)
368 { 564 {
369 XFontStruct *f = info + i; 565 rxvt_fontprop p;
370 if (f->ascent + f->descent <= maxheight) // weed out too large fonts 566 char fname[1024];
567 fix_scalable (fname, list[i], prop);
568
569 if (!set_properties (p, fname))
570 continue;
571
572 if (p.height > prop.height) // weed out too large fonts
573 continue;
574
575 int diff = (prop.height - p.height) * 32
576 + abs (prop.weight - p.weight)
577 + abs (prop.slant - p.slant );
578
371 if (!best // compare against best found so far 579 if (!name // compare against best found so far
372 || best->ascent + best->descent < f->ascent + f->descent) 580 || diff < bestdiff)
581 {
582 set_name (strdup (fname));
373 best = f; 583 bestdiff = diff;
584 }
374 } 585 }
375 586
376 set_name (strdup (list[best - info])); 587 XFreeFontNames (list);
377 588
378 XFreeFontInfo (list, info, count); 589 if (!name)
590 return false;
379 591
380 f = XLoadQueryFont (DISPLAY, name); 592 f = XLoadQueryFont (DISPLAY, name);
381 593
382 if (!f) 594 if (!f)
383 return false; 595 return false;
384 596
385 unsigned long value;
386
387 const char *registry = get_property ("CHARSET_REGISTRY", 0); 597 const char *registry = get_property (f, "CHARSET_REGISTRY", 0);
388 const char *encoding = get_property ("CHARSET_ENCODING", 0); 598 const char *encoding = get_property (f, "CHARSET_ENCODING", 0);
389 599
390 if (registry && encoding) 600 if (registry && encoding)
391 { 601 {
392 char charset[64]; 602 char charset[64];
393 snprintf (charset, 64, "%s-%s", registry, encoding); 603 snprintf (charset, 64, "%s-%s", registry, encoding);
394 604
395 cs = codeset_from_name (charset); 605 cs = codeset_from_name (charset);
396 } 606 }
397 else 607 else
398 { 608 {
399 const char *charset = get_property ("FONT", 0); 609 const char *charset = get_property (f, "FONT", 0);
400 610
401 if (!charset) 611 if (!charset)
402 charset = name; 612 charset = name;
403 613
404 int count = 13; 614 int count = 13;
417 627
418 ascent = f->ascent; 628 ascent = f->ascent;
419 descent = f->descent; 629 descent = f->descent;
420 height = ascent + descent; 630 height = ascent + descent;
421 631
422 prop = false; 632 slow = false;
423 633
424 if (f->min_bounds.width == f->max_bounds.width) 634 if (f->min_bounds.width == f->max_bounds.width)
425 width = f->min_bounds.width; 635 width = f->min_bounds.width;
426 else if (f->per_char == NULL) 636 else if (f->per_char == NULL)
427 width = f->max_bounds.width; 637 width = f->max_bounds.width;
428 else 638 else
429 { 639 {
430 prop = true; 640 slow = true;
431 641
432 int N = f->max_char_or_byte2 - f->min_char_or_byte2; 642 int N = f->max_char_or_byte2 - f->min_char_or_byte2;
433 643
434 if (encm) 644 if (encm)
435 N += (f->max_byte1 - f->min_byte1) 645 N += (f->max_byte1 - f->min_byte1)
465 f = 0; 675 f = 0;
466 } 676 }
467} 677}
468 678
469bool 679bool
470rxvt_font_x11::has_codepoint (uint32_t unicode) 680rxvt_font_x11::has_codepoint (unicode_t unicode)
471{ 681{
472 uint32_t ch = FROM_UNICODE (cs, unicode); 682 uint32_t ch = FROM_UNICODE (cs, unicode);
473 683
474 if (ch == NOCHAR) 684 if (ch == NOCHAR)
475 return false; 685 return false;
477 /* check wether the character exists in _this_ font. horrible. */ 687 /* check wether the character exists in _this_ font. horrible. */
478 XCharStruct *xcs; 688 XCharStruct *xcs;
479 689
480 if (encm) 690 if (encm)
481 { 691 {
482 int byte1 = ch >> 8; 692 unsigned char byte1 = ch >> 8;
483 int byte2 = ch & 255; 693 unsigned char byte2 = ch & 255;
484 694
485 if (byte1 < f->min_byte1 || byte1 > f->max_byte1 695 if (byte1 < f->min_byte1 || byte1 > f->max_byte1
486 || byte2 < f->min_char_or_byte2 || byte2 > f->max_char_or_byte2) 696 || byte2 < f->min_char_or_byte2 || byte2 > f->max_char_or_byte2)
487 return false; 697 return false;
488 698
511 721
512 return true; 722 return true;
513} 723}
514 724
515void 725void
516rxvt_font_x11::draw (int x, int y, 726rxvt_font_x11::draw (rxvt_drawable &d, int x, int y,
517 const text_t *text, int len, 727 const text_t *text, int len,
518 int fg, int bg) 728 int fg, int bg)
519{ 729{
520 // this looks like a mess /. 730 // this looks like a mess /.
521 // and it is a mess /. 731 // and it is a mess /.
522 // yet we are trying to be perfect /. 732 // yet we are trying to be perfect /.
523 // but the result still isn't perfect /. 733 // but the result still isn't perfect /.
524 734
525 bool slow = prop 735 bool slow = this->slow
526 || width != r->TermWin.fwidth 736 || width != r->TermWin.fwidth
527 || height != r->TermWin.fheight; 737 || height != r->TermWin.fheight;
528 738
529 int base = r->TermWin.fbase; 739 int base = r->TermWin.fbase;
530 740
537 { 747 {
538 const XChar2b *xc = enc_xchar2b (text, len, cs, slow); 748 const XChar2b *xc = enc_xchar2b (text, len, cs, slow);
539 749
540 if (bg == Color_bg && !slow) 750 if (bg == Color_bg && !slow)
541 { 751 {
542 XChangeGC (DISPLAY, GC, GCForeground | GCBackground | GCFont, &v); 752 XChangeGC (d.display->display, GC, GCForeground | GCBackground | GCFont, &v);
543 XDrawImageString16 (DISPLAY, DRAWABLE, GC, x, y + base, xc, len); 753 XDrawImageString16 (d.display->display, d, GC, x, y + base, xc, len);
544 } 754 }
545 else 755 else
546 { 756 {
547 clear_rect (x, y, r->TermWin.fwidth * len, r->TermWin.fheight, bg); 757 clear_rect (d, x, y, r->TermWin.fwidth * len, r->TermWin.fheight, bg);
548 758
549 XChangeGC (DISPLAY, GC, GCForeground | GCFont, &v); 759 XChangeGC (d.display->display, GC, GCForeground | GCFont, &v);
550 760
551 if (slow) 761 if (slow)
552 { 762 {
553 do 763 do
554 { 764 {
555 if (xc->byte1 || xc->byte2) 765 if (xc->byte1 || xc->byte2)
556 XDrawString16 (DISPLAY, DRAWABLE, GC, x, y + base, xc, 1); 766 XDrawString16 (d.display->display, d, GC, x, y + base, xc, 1);
557 767
558 x += r->TermWin.fwidth; 768 x += r->TermWin.fwidth;
559 xc++; len--; 769 xc++; len--;
560 } 770 }
561 while (len); 771 while (len);
562 } 772 }
563 else 773 else
564 XDrawString16 (DISPLAY, DRAWABLE, GC, x, y + base, xc, len); 774 XDrawString16 (d.display->display, d, GC, x, y + base, xc, len);
565 } 775 }
566 } 776 }
567 else 777 else
568 { 778 {
569 const char *xc = enc_char (text, len, cs, slow); 779 const char *xc = enc_char (text, len, cs, slow);
570 780
571 if (bg == Color_bg && !slow) 781 if (bg == Color_bg && !slow)
572 { 782 {
573 XChangeGC (DISPLAY, GC, GCForeground | GCBackground | GCFont, &v); 783 XChangeGC (d.display->display, GC, GCForeground | GCBackground | GCFont, &v);
574 XDrawImageString (DISPLAY, DRAWABLE, GC, x, y + base, xc, len); 784 XDrawImageString (d.display->display, d, GC, x, y + base, xc, len);
575 } 785 }
576 else 786 else
577 { 787 {
578 clear_rect (x, y, r->TermWin.fwidth * len, r->TermWin.fheight, bg); 788 clear_rect (d, x, y, r->TermWin.fwidth * len, r->TermWin.fheight, bg);
579 789
580 XChangeGC (DISPLAY, GC, GCForeground | GCFont, &v); 790 XChangeGC (d.display->display, GC, GCForeground | GCFont, &v);
581 791
582 if (slow) 792 if (slow)
583 { 793 {
584 do 794 do
585 { 795 {
586 if (*xc) 796 if (*xc)
587 XDrawString (DISPLAY, DRAWABLE, GC, x, y + base, xc, 1); 797 XDrawString (d.display->display, d, GC, x, y + base, xc, 1);
588 798
589 x += r->TermWin.fwidth; 799 x += r->TermWin.fwidth;
590 xc++; len--; 800 xc++; len--;
591 } 801 }
592 while (len); 802 while (len);
593 } 803 }
594 else 804 else
595 XDrawString (DISPLAY, DRAWABLE, GC, x, y + base, xc, len); 805 XDrawString (d.display->display, d, GC, x, y + base, xc, len);
596 } 806 }
597 } 807 }
598} 808}
599 809
600///////////////////////////////////////////////////////////////////////////// 810/////////////////////////////////////////////////////////////////////////////
605//#define SWATHBITS (UNIBITS / 2 + 3) // minimum size for "full" tables 815//#define SWATHBITS (UNIBITS / 2 + 3) // minimum size for "full" tables
606#define SWATHBITS 8 816#define SWATHBITS 8
607#endif 817#endif
608 818
609struct rxvt_font_xft : rxvt_font { 819struct rxvt_font_xft : rxvt_font {
610#if 0
611 enum {
612 SWATHCOUNT = 1 << (21 - UNIBITS),
613 SWATHSIZE = 1 << (SWATHBITS - 5)
614 };
615 typedef uint32_t swath[SWATHSIZE];
616
617 swath *cvr[SWATHCOUNT];
618#endif
619
620#if 0
621 void gen_coverage_swath (unsigned int page);
622
623 bool has_char (uint32_t ch)
624 {
625 unsigned int page = ch >> SWATHBITS;
626 unsigned int idx = ch & ((1 << SWATHBITS) - 1);
627
628 if (page >= SWATHCOUNT)
629 return false;
630
631 if (!cvr[page]) gen_coverage_swath (page);
632
633 return cvr[page][idx >> 5] & (1 << (idx & 31));
634 }
635#endif
636 rxvt_font_xft () { f = 0; d = 0; } 820 rxvt_font_xft () { f = 0; }
637 821
638 void clear (); 822 void clear ();
639 823
640 bool load (int maxheight); 824 rxvt_fontprop properties ();
641 825
642 void draw (int x, int y, 826 bool load (const rxvt_fontprop &prop);
827
828 void draw (rxvt_drawable &d, int x, int y,
643 const text_t *text, int len, 829 const text_t *text, int len,
644 int fg, int bg); 830 int fg, int bg);
645 831
646 bool has_codepoint (uint32_t unicode); 832 bool has_codepoint (unicode_t unicode);
647 833
648protected: 834protected:
649 XftFont *f; 835 XftFont *f;
650 XftDraw *d;
651
652#if 0
653 virtual void populate_coverage_swath (uint32_t lo, uint32_t hi) = 0;
654 void set_swath (uint32_t ch)
655 {
656 cvr[ch >> SWATHBITS] |= 1 << (ch & ((1 << SWATHBITS) - 1));
657 }
658#endif
659}; 836};
660 837
661void 838void
662rxvt_font_xft::clear () 839rxvt_font_xft::clear ()
663{ 840{
664 if (f) 841 if (f)
665 { 842 {
666 XftFontClose (DISPLAY, f); 843 XftFontClose (DISPLAY, f);
667 f = 0; 844 f = 0;
668 } 845 }
846}
669 847
670 if (d) 848rxvt_fontprop
671 { 849rxvt_font_xft::properties ()
672 XftDrawDestroy (d); 850{
673 d = 0; 851 rxvt_fontprop p;
674 }
675 852
676#if 0 853 FT_Face face = XftLockFace (f);
677 for (int i = 0; i < SWATHCOUNT; i++) 854
678 delete cvr[i]; 855 p.width = width; p.height = height;
679#endif 856 p.weight = face->style_flags & FT_STYLE_FLAG_BOLD ? rxvt_fontprop::bold : rxvt_fontprop::medium;
857 p.slant = face->style_flags & FT_STYLE_FLAG_ITALIC ? rxvt_fontprop::italic : rxvt_fontprop::roman;
858
859 XftUnlockFace (f);
860
861 return p;
680} 862}
681 863
682bool 864bool
683rxvt_font_xft::load (int maxheight) 865rxvt_font_xft::load (const rxvt_fontprop &prop)
684{ 866{
685#if 0 867#if 0
686 for (int i = 0; i < SWATHCOUNT; i++) 868 for (int i = 0; i < SWATHCOUNT; i++)
687 cvr[i] = 0; 869 cvr[i] = 0;
688#endif 870#endif
689 871
690 clear (); 872 clear ();
691 873
692 f = XftFontOpenName (DISPLAY, DefaultScreen (DISPLAY), name); 874 FcPattern *p = FcNameParse ((FcChar8 *) name);
875
876 if (!p)
877 return false;
878
879 FcValue v;
880
881 if (FcPatternGet (p, FC_WEIGHT, 0, &v) != FcResultMatch)
882 FcPatternAddInteger (p, FC_WEIGHT, prop.weight);
883
884 if (FcPatternGet (p, FC_SLANT, 0, &v) != FcResultMatch)
885 FcPatternAddInteger (p, FC_SLANT, prop.slant);
886
887#if 0 // clipping unfortunately destroys our precious double-width-characters
888 // clip width, we can't do better, or can we?
889 if (FcPatternGet (p, FC_CHAR_WIDTH, 0, &v) != FcResultMatch)
890 FcPatternAddInteger (p, FC_CHAR_WIDTH, prop.width);
891#endif
892
893 //FcPatternAddBool (p, FC_MINSPACE, 1);
894
895 XftResult result;
896 FcPattern *match = XftFontMatch (DISPLAY, DefaultScreen (DISPLAY), p, &result);
897
898 FcPatternDestroy (p);
899
900 if (!match)
901 return false;
902
903 f = XftFontOpenPattern (DISPLAY, match);
693 904
694 if (!f) 905 if (!f)
906 {
907 FcPatternDestroy (match);
695 return false; 908 return false;
909 }
696 910
697 FT_Face face = XftLockFace (f); 911 FT_Face face = XftLockFace (f);
698 912
699 prop = !FT_IS_FIXED_WIDTH (face); 913 slow = !FT_IS_FIXED_WIDTH (face);
700 914
701 int ftheight = 0; 915 int ftheight = 0;
702 916
703 for (;;) 917 for (;;)
704 { 918 {
706 FcChar8 c; 920 FcChar8 c;
707 921
708 c = 'i'; XftTextExtents8 (DISPLAY, f, &c, 1, &g1); 922 c = 'i'; XftTextExtents8 (DISPLAY, f, &c, 1, &g1);
709 c = 'W'; XftTextExtents8 (DISPLAY, f, &c, 1, &g2); 923 c = 'W'; XftTextExtents8 (DISPLAY, f, &c, 1, &g2);
710 924
711 prop = prop || g1.xOff != g2.xOff; // don't simply trust the font 925 if (g1.xOff != g2.xOff) // don't simply trust the font
926 slow = true;
712 927
713 width = g2.xOff; 928 width = g2.xOff;
714 ascent = (face->size->metrics.ascender + 63) >> 6; 929 ascent = (face->size->metrics.ascender + 63) >> 6;
715 descent = (-face->size->metrics.descender + 63) >> 6; 930 descent = (-face->size->metrics.descender + 63) >> 6;
716 height = ascent + descent; 931 height = ascent + descent;
717 932
718 if (height <= maxheight || !maxheight) 933 if (height <= prop.height || !prop.height)
719 break; 934 break;
720 935
721 if (ftheight) 936 if (ftheight)
722 { 937 {
723 // take smaller steps near the end 938 // take smaller steps near the end
724 if (height > maxheight + 1) ftheight++; 939 if (height > prop.height + 1) ftheight++;
725 if (height > maxheight + 2) ftheight++; 940 if (height > prop.height + 2) ftheight++;
726 if (height > maxheight + 3) ftheight++; 941 if (height > prop.height + 3) ftheight++;
727 942
728 FT_Set_Pixel_Sizes (face, 0, ftheight -= height - maxheight); 943 FT_Set_Pixel_Sizes (face, 0, ftheight -= height - prop.height);
729 } 944 }
730 else 945 else
731 FT_Set_Pixel_Sizes (face, 0, ftheight = maxheight); 946 FT_Set_Pixel_Sizes (face, 0, ftheight = prop.height);
732 } 947 }
733 948
734 XftUnlockFace (f); 949 XftUnlockFace (f);
735 950
736 return true; 951 return true;
737} 952}
738 953
739#if 0
740void rxvt_font::gen_coverage_swath (unsigned int page)
741{
742 cvr[page] = new swath;
743
744 for (int i = 0; i < SWATHSIZE; i++)
745 cvr[page][i] = 0;
746
747 populate_coverage_swath (cvr[page], page << SWATHBITS, ((page + 1) << SWATHBITS) - 1);
748}
749#endif
750
751bool 954bool
752rxvt_font_xft::has_codepoint (uint32_t unicode) 955rxvt_font_xft::has_codepoint (unicode_t unicode)
753{ 956{
754 return XftCharExists (DISPLAY, f, unicode); 957 return XftCharExists (DISPLAY, f, unicode);
755} 958}
756 959
757void 960void
758rxvt_font_xft::draw (int x, int y, 961rxvt_font_xft::draw (rxvt_drawable &d, int x, int y,
759 const text_t *text, int len, 962 const text_t *text, int len,
760 int fg, int bg) 963 int fg, int bg)
761{ 964{
762 if (!d)
763 {
764 dR;
765 d = XftDrawCreate (DISPLAY, DRAWABLE, XVISUAL, XCMAP);
766 }
767
768 if (bg >= 0 && bg != Color_bg)
769 XftDrawRect (d, &r->PixColors[bg].c, x, y, r->TermWin.fwidth * len, r->TermWin.fheight);
770 else
771 clear_rect (x, y, r->TermWin.fwidth * len, r->TermWin.fheight, bg); 965 clear_rect (d, x, y, r->TermWin.fwidth * len, r->TermWin.fheight, bg);
772 966
773 if (!prop && width == r->TermWin.fwidth) 967 if (!slow && width == r->TermWin.fwidth && 0)
774 { 968 {
775 if (sizeof (text_t) == sizeof (FcChar16)) 969 if (sizeof (text_t) == sizeof (FcChar16))
776 XftDrawString16 (d, &r->PixColors[fg].c, f, x, y + r->TermWin.fbase, (const FcChar16 *)text, len); 970 XftDrawString16 (d, &r->PixColors[fg].c, f, x, y + r->TermWin.fbase, (const FcChar16 *)text, len);
777 else 971 else
778 XftDrawString32 (d, &r->PixColors[fg].c, f, x, y + r->TermWin.fbase, (const FcChar32 *)text, len); 972 XftDrawString32 (d, &r->PixColors[fg].c, f, x, y + r->TermWin.fbase, (const FcChar32 *)text, len);
781 { 975 {
782 while (len) 976 while (len)
783 { 977 {
784 if (*text != NOCHAR && *text != ' ') 978 if (*text != NOCHAR && *text != ' ')
785 { 979 {
980 int fwidth = r->TermWin.fwidth;
981 if (len >= 2 && text[1] == NOCHAR)
982 fwidth *= 2;
983
984 XGlyphInfo extents;
786 if (sizeof (text_t) == sizeof (FcChar16)) 985 if (sizeof (text_t) == sizeof (FcChar16))
787 XftDrawString16 (d, &r->PixColors[fg].c, f, x, y + r->TermWin.fbase, (const FcChar16 *)text, 1); 986 {
987 XftTextExtents16 (d.display->display, f, (const FcChar16 *)text, 1, &extents);
988 XftDrawString16 (d, &r->PixColors[fg].c, f, x + extents.x + (fwidth - extents.width) / 2,
989 y + r->TermWin.fbase, (const FcChar16 *)text, 1);
990 }
788 else 991 else
789 XftDrawString32 (d, &r->PixColors[fg].c, f, x, y + r->TermWin.fbase, (const FcChar32 *)text, 1); 992 {
993 XGlyphInfo extents;
994 XftTextExtents32 (d.display->display, f, (const FcChar32 *)text, 1, &extents);
995 XftDrawString32 (d, &r->PixColors[fg].c, f, x + extents.x + (fwidth - extents.width) / 2,
996 y + r->TermWin.fbase, (const FcChar32 *)text, 1);
997 }
790 } 998 }
791 999
792 x += r->TermWin.fwidth; 1000 x += r->TermWin.fwidth;
793 text++; 1001 text++;
794 len--; 1002 len--;
798#endif 1006#endif
799 1007
800///////////////////////////////////////////////////////////////////////////// 1008/////////////////////////////////////////////////////////////////////////////
801 1009
802rxvt_fontset::rxvt_fontset (rxvt_t r) 1010rxvt_fontset::rxvt_fontset (rxvt_t r)
803#ifdef EXPLICIT_CONTEXT
804: r(r) 1011: r (r)
805#endif
806{ 1012{
807 clear (); 1013 clear ();
808} 1014}
809 1015
810rxvt_fontset::~rxvt_fontset () 1016rxvt_fontset::~rxvt_fontset ()
813} 1019}
814 1020
815void 1021void
816rxvt_fontset::clear () 1022rxvt_fontset::clear ()
817{ 1023{
818 for (rxvt_font **i = fonts.begin (); i != fonts.end(); i++) 1024 for (rxvt_font **i = fonts.begin (); i != fonts.end (); i++)
819 FONT_UNREF (*i); 1025 FONT_UNREF (*i);
820 1026
821 fonts.clear (); 1027 fonts.clear ();
822 base_id = 0; 1028 base_id = 0;
823 height = 0x7fffffff; 1029 base_prop.height = 0x7fffffff;
1030 base_prop.weight = rxvt_fontprop::medium;
1031 base_prop.slant = rxvt_fontprop::roman;
824 1032
825 fallback = fallback_fonts; 1033 fallback = fallback_fonts;
826} 1034}
827 1035
828rxvt_font * 1036rxvt_font *
848 f = new rxvt_font_x11; 1056 f = new rxvt_font_x11;
849 } 1057 }
850 else 1058 else
851 f = new rxvt_font_x11; 1059 f = new rxvt_font_x11;
852 1060
1061 f->fs = this;
853 f->set_term (r); 1062 f->set_term (r);
854 f->set_name (strdup (name)); 1063 f->set_name (strdup (name));
855 1064
856 f->cs = cs; 1065 f->cs = cs;
857 f->loaded = false; 1066 f->loaded = false;
875 1084
876 if (*desc == '[') 1085 if (*desc == '[')
877 { 1086 {
878 fprintf (stderr, "extra font parameters not yet supported, skipping.\n"); 1087 fprintf (stderr, "extra font parameters not yet supported, skipping.\n");
879 1088
880 const char *extra = desc++; 1089 //const char *extra = desc++; // not yet used
881 1090
882 desc = strchr (desc, ']'); 1091 desc = strchr (desc, ']');
883 1092
884 if (!desc) 1093 if (!desc)
885 { 1094 {
915 if (fonts[i]->loaded) 1124 if (fonts[i]->loaded)
916 return true; 1125 return true;
917 1126
918 fonts[i]->loaded = true; 1127 fonts[i]->loaded = true;
919 1128
920 if (!fonts[i]->load (height)) 1129 if (!fonts[i]->load (base_prop))
921 { 1130 {
922 fonts[i]->cs = CS_UNKNOWN; 1131 fonts[i]->cs = CS_UNKNOWN;
923 return false; 1132 return false;
924 } 1133 }
925 1134
926 return true; 1135 return true;
927} 1136}
928 1137
929void 1138bool
930rxvt_fontset::populate (const char *desc) 1139rxvt_fontset::populate (const char *desc)
931{ 1140{
932 clear (); 1141 clear ();
933 1142
934 fonts.push_back (new_font (0, CS_UNICODE)); 1143 fonts.push_back (new_font (0, CS_UNICODE));
938 1147
939 if (!base_id) 1148 if (!base_id)
940 base_id = 1; 1149 base_id = 1;
941 1150
942 // we currently need a base-font, no matter what 1151 // we currently need a base-font, no matter what
943 if (fonts.size () <= base_id) 1152 if ((int)fonts.size () <= base_id || !realize_font (base_id))
944 { 1153 {
1154 puts ("unable to load specified font (s), falling back to 'fixed'\n");
945 add_fonts ("fixed"); 1155 add_fonts ("fixed");
946 base_id = 1; 1156 base_id = fonts.size () - 1;
947 } 1157 }
948 1158
949 if (fonts.size () <= base_id || !realize_font (base_id)) 1159 if ((int)fonts.size () <= base_id || !realize_font (base_id))
950 { 1160 return false;
951 fprintf (stderr, "unable to load a base font, please provide one using -fn fontname\n");
952 exit (1);
953 }
954 1161
955 height = fonts[base_id]->height; 1162 base_prop = fonts[base_id]->properties ();
956 1163
957 /*add_fonts ("-efont-fixed-medium-r-normal-*-14-*-*-*-*-*-iso10646-1,"*/ 1164 return true;
958} 1165}
959 1166
960int 1167int
961rxvt_fontset::find_font (uint32_t unicode) 1168rxvt_fontset::find_font (unicode_t unicode)
962{ 1169{
963 for (int i = 0; i < fonts.size (); i++) 1170 for (unsigned int i = 0; i < fonts.size (); i++)
964 { 1171 {
965 rxvt_font *f = fonts[i]; 1172 rxvt_font *f = fonts[i];
966 1173
967 if (!f->loaded) 1174 if (!f->loaded)
968 { 1175 {

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines