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.9 by pcg, Wed Dec 24 06:26:52 2003 UTC vs.
Revision 1.43 by pcg, Mon Mar 15 07:10:47 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
23#include "rxvt.h" 23#include "rxvt.h"
24#include "defaultfont.h" 24#include "defaultfont.h"
25 25
26#include <cstdlib> 26#include <cstdlib>
27 27
28#define DISPLAY r->Xdisplay 28#define DISPLAY r->display->display
29#define DRAWABLE r->TermWin.vt
30#define GC r->TermWin.gc 29#define TGC r->TermWin.gc
31 30
32const struct rxvt_fallback_font { 31const struct rxvt_fallback_font {
33 codeset cs; 32 codeset cs;
34 const char *name; 33 const char *name;
35} fallback_fonts[] = { 34} fallback_fonts[] = {
62# if XFT 61# if XFT
63 // prefer xft for complex scripts 62 // prefer xft for complex scripts
64 { CS_UNICODE, "xft:Kochi Gothic:antialias=false" }, 63 { CS_UNICODE, "xft:Kochi Gothic:antialias=false" },
65# endif 64# endif
66 { CS_JIS0201_1976_0, "-*-mincho-*-r-*--*-*-*-*-c-*-jisx0201*-0" }, 65 { CS_JIS0201_1976_0, "-*-mincho-*-r-*--*-*-*-*-c-*-jisx0201*-0" },
67 { CS_JIS0208_1983_0, "-*-mincho-*-r-*--*-*-*-*-c-*-jisx0208*-0" }, 66 { CS_JIS0208_1990_0, "-*-mincho-*-r-*--*-*-*-*-c-*-jisx0208*-0" },
68 { CS_JIS0212_1990_0, "-*-mincho-*-r-*--*-*-*-*-c-*-jisx0212*-0" }, 67 { CS_JIS0212_1990_0, "-*-mincho-*-r-*--*-*-*-*-c-*-jisx0212*-0" },
69#endif 68#endif
70 69
71#if ENCODING_CN || ENCODING_CN_EXT 70#if ENCODING_CN || ENCODING_CN_EXT
72# if XFT 71# if XFT
73 { CS_BIG5_EXT, "xft:AR PL Mingti2L Big5" }, 72 { CS_BIG5_EXT, "xft:AR PL Mingti2L Big5" },
74 { CS_BIG5_EXT, "xft:AR PL KaitiM Big5" }, 73 { CS_BIG5_EXT, "xft:AR PL KaitiM Big5" },
75 { CS_GB2312_1980_0, "xft:AR PL KaitiM GB" }, 74 { CS_GB2312_1980_0, "xft:AR PL KaitiM GB" },
76 { CS_GB2312_1980_0, "xft:AR PL SungtiL GB" }, 75 { CS_GB2312_1980_0, "xft:AR PL SungtiL GB" },
77# 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" },
78 { CS_CNS11643_1992_1, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643.1992-1" }, 81 { CS_CNS11643_1992_1, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-1" },
79 { CS_CNS11643_1992_2, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643.1992-2" }, 82 { CS_CNS11643_1992_2, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-2" },
80 { CS_CNS11643_1992_3, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643.1992-3" }, 83 { CS_CNS11643_1992_3, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-3" },
81 { CS_CNS11643_1992_4, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643.1992-4" }, 84 { CS_CNS11643_1992_4, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-4" },
82 { CS_CNS11643_1992_5, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643.1992-5" }, 85 { CS_CNS11643_1992_5, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-5" },
83 { CS_CNS11643_1992_6, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643.1992-6" }, 86 { CS_CNS11643_1992_6, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-6" },
84 { CS_CNS11643_1992_7, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643.1992-7" }, 87 { CS_CNS11643_1992_7, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-7" },
85 { CS_CNS11643_1992_F, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643.1992-f" }, 88 { CS_CNS11643_1992_F, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-f" },
86#endif 89#endif
87 90
88#if XFT 91#if XFT
89 { CS_UNICODE, "xft:Andale Mono" }, 92 { CS_UNICODE, "xft:Andale Mono" },
90 { CS_UNICODE, "xft:Arial Unicode MS" }, 93 { CS_UNICODE, "xft:Arial Unicode MS" },
93 { CS_UNICODE, "xft:FreeMono" }, 96 { CS_UNICODE, "xft:FreeMono" },
94 { CS_UNICODE, "-*-unifont-*-*-*-*-*-*-*-*-c-*-iso10646-1" }, 97 { CS_UNICODE, "-*-unifont-*-*-*-*-*-*-*-*-c-*-iso10646-1" },
95 { CS_UNICODE, "-*-*-*-r-*-*-*-*-*-*-c-*-iso10646-1" }, 98 { CS_UNICODE, "-*-*-*-r-*-*-*-*-*-*-c-*-iso10646-1" },
96 { CS_UNICODE, "-*-*-*-r-*-*-*-*-*-*-m-*-iso10646-1" }, 99 { CS_UNICODE, "-*-*-*-r-*-*-*-*-*-*-m-*-iso10646-1" },
97 100
101#if UNICODE_3 && XFT
102 { CS_UNICODE, "xft:Code2001" }, // contains many plane-1 characters
103#endif
104
98 { CS_UNKNOWN, 0 } 105 { CS_UNKNOWN, 0 }
99}; 106};
100 107
101///////////////////////////////////////////////////////////////////////////// 108/////////////////////////////////////////////////////////////////////////////
102 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
103static void *enc_buf; 128static void *enc_buf;
104static uint32_t enc_len; 129static uint32_t enc_len;
105 130
106static inline void * 131static inline void *
107get_enc_buf (int len) 132get_enc_buf (uint32_t len)
108{ 133{
109 if (len > enc_len) 134 if (len > enc_len)
110 { 135 {
111 free (enc_buf); 136 free (enc_buf);
112 enc_buf = malloc (len); 137 enc_buf = malloc (len);
114 139
115 return enc_buf; 140 return enc_buf;
116} 141}
117 142
118static const char * 143static const char *
119enc_char (const text_t *text, int len, codeset cs, bool &zero) 144enc_char (const text_t *text, uint32_t len, codeset cs, bool &zero)
120{ 145{
121 uint8_t *buf = (uint8_t *)get_enc_buf (len); 146 uint8_t *buf = (uint8_t *)get_enc_buf (len);
122 147
123 while (len--) 148 while (len--)
124 { 149 {
135 160
136 return (const char *)enc_buf; 161 return (const char *)enc_buf;
137} 162}
138 163
139static const XChar2b * 164static const XChar2b *
140enc_xchar2b (const text_t *text, int len, codeset cs, bool &zero) 165enc_xchar2b (const text_t *text, uint32_t len, codeset cs, bool &zero)
141{ 166{
142 XChar2b *buf = (XChar2b *)get_enc_buf (len * sizeof (XChar2b)); 167 XChar2b *buf = (XChar2b *)get_enc_buf (len * sizeof (XChar2b));
143 168
144 while (len--) 169 while (len--)
145 { 170 {
160} 185}
161 186
162///////////////////////////////////////////////////////////////////////////// 187/////////////////////////////////////////////////////////////////////////////
163 188
164void 189void
165rxvt_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)
166{ 191{
167 if (color == Color_bg) 192 if (color == Color_bg)
168 XClearArea (DISPLAY, DRAWABLE, x, y, w, h, FALSE); 193 XClearArea (d.display->display, d, x, y, w, h, FALSE);
169 else if (color >= 0) 194 else if (color >= 0)
170 { 195 {
196#if XFT
197 XftDrawRect (d, &r->PixColors[color].c, x, y, w, h);
198#else
171 XSetForeground (DISPLAY, GC, r->PixColors[color]); 199 XSetForeground (d.display->display, TGC, r->PixColors[color]);
172 XFillRectangle (DISPLAY, DRAWABLE, GC, x, y, w, h); 200 XFillRectangle (d.display->display, d, TGC, x, y, w, h);
201#endif
173 } 202 }
174} 203}
175 204
176static const char *linedraw_cmds[128] = { 205static const char *linedraw_cmds[128 + 32] = {
177 "1hH", "2hH", "1vV", "2vV", 206 "1-", "2-", "1|", "2|",
178 0, 0, 0, 0, 207 0, 0, 0, 0,
179 0, 0, 0, 0, 208 0, 0, 0, 0,
180 "1HV", "2H1V", "1H2V", "2HV", 209 "1HV", "2H1V", "1H2V", "2HV",
181 210
182 // 2510 211 // 2510
183 "1hV", "2h1V", "1h2V", "2hV", 212 "1hV", "2h1V", "1h2V", "2hV",
184 "1Hv", "2H1v", "1H2v", "2Hv", 213 "1Hv", "2H1v", "1H2v", "2Hv",
185 "1hv", "2h1v", "1h2v", "2hv", 214 "1hv", "2h1v", "1h2v", "2hv",
186 "1HvV", "2H1vV", "1HV2v", "1Hv2V", 215 "1H|", "2H1|", "1HV2v", "1Hv2V",
187 216
188 // 2520 217 // 2520
189 "1H2vV", "2Hv1V", "2HV1v", "2HvV", 218 "1H2|", "2Hv1V", "2HV1v", "2H|",
190 "1hvV", "2h1vV", "1hV2v", "1hv2V", 219 "1h|", "2h1|", "1hV2v", "1hv2V",
191 "1h2vV", "2hv1V", "1v2hV", "2hvV", 220 "1h2|", "2hv1V", "1v2hV", "2h|",
192 "1hHV", "2h1HV", "2H1hV", "2hH1V", 221 "1-V", "2h1HV", "2H1hV", "2-1V",
193 222
194 // 2530 223 // 2530
195 "1hH2V", "2hV1H", "1h2HV", "2hHV", 224 "1-2V", "2hV1H", "1h2HV", "2-V",
196 "1hHv", "1vH2h", "1hv2H", "1v2hH", 225 "1-v", "1vH2h", "1hv2H", "1v2-",
197 "1hH2v", "1H2hv", "1h2Hv", "2hHv", 226 "1-2v", "1H2hv", "1h2Hv", "2-v",
198 "1hHvV", "1vVH2h", "1hvV2H", "1vV2hH", 227 "1-|", "1|H2h", "1h|2H", "1|2-",
199 228
200 // 2540 229 // 2540
201 "1hHV2v", "1hHv2V", "1hH2vV", "1HV2hv", 230 "1-V2v", "1-v2V", "1-2|", "1HV2hv",
202 "1hV2Hv", "1Hv2hV", "1hv2HV", "1V2hHv", 231 "1hV2Hv", "1Hv2hV", "1hv2HV", "1V2-v",
203 "1v2hHV", "1H2hvV", "1h2HvV", "2hHvV", 232 "1v2-V", "1H2h|", "1h2H|", "2-|",
204 0, 0, 0, 0, 233 0, 0, 0, 0,
205 234
206 // 2550 235 // 2550
207 0, 0, 0, 0, 236 0, 0, 0, 0,
208 0, 0, 0, 0, 237 0, 0, 0, 0,
211 240
212 // 2560 241 // 2560
213 0, 0, 0, 0, 242 0, 0, 0, 0,
214 0, 0, 0, 0, 243 0, 0, 0, 0,
215 0, 0, 0, 0, 244 0, 0, 0, 0,
216 0, 0, 0, 0, 245 0, "A", "B", "C",
217 246
218 // 2570 247 // 2570
219 0, "1a", "1b", "1ab", 248 "D", "1/", "1\\", "1/\\",
220 "1h", "1v", "1H", "1V", 249 "1h", "1v", "1H", "1V",
221 "2h", "2v", "2H", "2V", 250 "2h", "2v", "2H", "2V",
222 "1h2H", "1v2V", "1H2h", "1V2v" 251 "1h2H", "1v2V", "1H2h", "1V2v",
252
253 // 2580
254 0, 0, 0, 0,
255 0, 0, 0, 0,
256 0, 0, 0, 0,
257 0, 0, 0, 0,
258
259 // 2590
260 0, 0, 0, 0,
261 0, 0, "k", "l",
262 "i", "ikl", "il", "ijk",
263 "ijl", "j", "jk", "jkl",
223 264
224 // to be done 265 // to be done
225}; 266};
226 267
227struct rxvt_font_default : rxvt_font { 268struct rxvt_font_default : rxvt_font {
228 rxvt_fontprop properties () 269 rxvt_fontprop properties ()
229 { 270 {
230 rxvt_fontprop p; 271 rxvt_fontprop p;
231 272
232 p.height = 1; 273 p.width = p.height = 1;
233 p.weight = rxvt_fontprop::medium; 274 p.weight = rxvt_fontprop::medium;
234 p.slant = rxvt_fontprop::roman; 275 p.slant = rxvt_fontprop::roman;
235 276
236 return p; 277 return p;
237 } 278 }
239 bool load (const rxvt_fontprop &prop) 280 bool load (const rxvt_fontprop &prop)
240 { 281 {
241 width = 1; height = 1; 282 width = 1; height = 1;
242 ascent = 1; descent = 0; 283 ascent = 1; descent = 0;
243 284
285 set_name ("built-in pseudofont");
286
244 return true; 287 return true;
245 } 288 }
246 289
247 bool has_codepoint (uint32_t unicode) 290 bool has_codepoint (unicode_t unicode)
248 { 291 {
249 if (unicode <= 0x001f) 292 if (unicode <= 0x001f)
250 return true; 293 return true;
294
251 if (unicode >= 0x0080 && unicode <= 0x009f) 295 if (unicode >= 0x0080 && unicode <= 0x009f)
252 return true; 296 return true;
253 297
254 if (unicode >= 0x2500 && unicode <= 0x257f 298 if (unicode >= 0x2500 && unicode <= 0x257f
255 && linedraw_cmds[unicode - 0x2500]) 299 && linedraw_cmds[unicode - 0x2500])
300 return true;
301
302 if (unicode >= 0x2580 && unicode <= 0x259f)
303 return true;
304
305 if (IS_COMPOSE (unicode))
256 return true; 306 return true;
257 307
258 switch (unicode) 308 switch (unicode)
259 { 309 {
260 case ZERO_WIDTH_CHAR: 310 case ZERO_WIDTH_CHAR:
262 } 312 }
263 313
264 return false; 314 return false;
265 } 315 }
266 316
267 void draw (int x, int y, 317 void draw (rxvt_drawable &d, int x, int y,
268 const text_t *text, int len, 318 const text_t *text, int len,
269 int fg, int bg); 319 int fg, int bg);
270}; 320};
271 321
322static void rect_stipple (Display *display, Drawable d, GC gc, int s1, int s2, int x, int y, int w, int h)
323{
324 XGCValues gcv;
325 char bm[2] = { s1, s2 };
326
327 gcv.fill_style = FillStippled;
328 gcv.stipple = XCreateBitmapFromData (display, d, bm, 2, 2);
329 gcv.ts_x_origin = x;
330 gcv.ts_y_origin = y;
331
332 if (!gcv.stipple)
333 return;
334
335 XChangeGC (display, gc, GCFillStyle | GCStipple | GCTileStipXOrigin | GCTileStipYOrigin, &gcv);
336 XFillRectangle (display, d, gc, x, y, w, h);
337
338 XFreePixmap (display, gcv.stipple);
339
340 gcv.fill_style = FillSolid;
341 XChangeGC (display, gc, GCFillStyle, &gcv);
342}
343
272void 344void
273rxvt_font_default::draw (int x, int y, 345rxvt_font_default::draw (rxvt_drawable &d, int x, int y,
274 const text_t *text, int len, 346 const text_t *text, int len,
275 int fg, int bg) 347 int fg, int bg)
276{ 348{
277 clear_rect (x, y, r->TermWin.fwidth * len, r->TermWin.fheight, bg); 349 clear_rect (d, x, y, r->TermWin.fwidth * len, r->TermWin.fheight, bg);
278 350
279 XSetForeground (DISPLAY, GC, r->PixColors[fg]); 351 XSetForeground (d.display->display, TGC, r->PixColors[fg]);
280 352
281 while (len--) 353 while (len--)
282 { 354 {
355#if ENABLE_COMBINING
356 compose_char *cc;
357#endif
283 text_t t = *text++; 358 text_t t = *text++;
284 359
360 int W = r->TermWin.fwidth , w = (W - 1) / 2;
361 int H = r->TermWin.fheight, h = (H - 1) / 2;
362 int x0 = x, x1 = x + w, x2 = x + r->TermWin.fwidth ;
363 int y0 = y, y1 = y + h, y2 = y + r->TermWin.fheight;
364
365 // is it in our linedrawing table?
285 if (t >= 0x2500 & t <= 0x2580 && linedraw_cmds[t - 0x2500]) 366 if (t >= 0x2500 & t <= 0x259f && linedraw_cmds[t - 0x2500])
286 { 367 {
287 const char *p = linedraw_cmds[t - 0x2500]; 368 const char *p = linedraw_cmds[t - 0x2500];
288 369
289 int x0 = x, x1 = x + r->TermWin.fwidth / 2, x2 = x + r->TermWin.fwidth ;
290 int y0 = y, y1 = y + r->TermWin.fheight / 2, y2 = y + r->TermWin.fheight;
291
292 XGCValues gcv; 370 XGCValues gcv;
371
372 gcv.cap_style = CapNotLast;
373 XChangeGC (d.display->display, TGC, GCCapStyle, &gcv);
293 374
294 while (*p) 375 while (*p)
295 { 376 {
296 switch (*p++) 377 switch (*p++)
297 { 378 {
298 case '1': 379 case '1':
299 gcv.line_width = 0; 380 gcv.line_width = 0;
300 XChangeGC (DISPLAY, GC, GCLineWidth, &gcv); 381 XChangeGC (d.display->display, TGC, GCLineWidth, &gcv);
301 break; 382 break;
302 383
303 case '2': 384 case '2':
304 gcv.line_width = 2; 385 gcv.line_width = 3;
305 XChangeGC (DISPLAY, GC, GCLineWidth, &gcv); 386 XChangeGC (d.display->display, TGC, GCLineWidth, &gcv);
306 break; 387 break;
307 388
308 case 'h': XDrawLine (DISPLAY, DRAWABLE, GC, x0, y1, x1, y1); break; 389 case 'h': XDrawLine (d.display->display, d, TGC, x0, y1, x1+1, y1 ); break;
309 case 'H': XDrawLine (DISPLAY, DRAWABLE, GC, x1, y1, x2, y1); break; 390 case 'H': XDrawLine (d.display->display, d, TGC, x1, y1, x2 , y1 ); break;
391 case '-': XDrawLine (d.display->display, d, TGC, x0, y1, x2 , y1 ); break;
310 case 'v': XDrawLine (DISPLAY, DRAWABLE, GC, x1, y0, x1, y1); break; 392 case 'v': XDrawLine (d.display->display, d, TGC, x1, y0, x1 , y1+1); break;
311 case 'V': XDrawLine (DISPLAY, DRAWABLE, GC, x1, y1, x1, y2); break; 393 case 'V': XDrawLine (d.display->display, d, TGC, x1, y1, x1 , y2 ); break;
394 case '|': XDrawLine (d.display->display, d, TGC, x1, y0, x1 , y2 ); break;
395
312 case 'a': XDrawLine (DISPLAY, DRAWABLE, GC, x0, y2, x2, y0); break; 396 case '/' : XDrawLine (d.display->display, d, TGC, x0, y2, x2 , y0 ); break;
313 case 'b': XDrawLine (DISPLAY, DRAWABLE, GC, x0, y0, x2, y2); break; 397 case '\\': XDrawLine (d.display->display, d, TGC, x0, y0, x2 , y2 ); break;
398
399 case 'A': XDrawArc (d.display->display, d, TGC, x1 , y1 , W-1, H-1, 90*64, 90*64); break;
400 case 'B': XDrawArc (d.display->display, d, TGC, x1-W+1, y1 , W-1, H-1, 0*64, 90*64); break;
401 case 'C': XDrawArc (d.display->display, d, TGC, x1-W+1, y1-H+1, W-1, H-1, 0*64, -90*64); break;
402 case 'D': XDrawArc (d.display->display, d, TGC, x1 , y1-H+1, W-1, H-1, -90*64, -90*64); break;
403
404 case 'i': XFillRectangle (d.display->display, d, TGC, x0, y0, x1 - x0 + 1, y1 - y0 + 1); break;
405 case 'j': XFillRectangle (d.display->display, d, TGC, x1, y0, x2 - x1, y1 - y0 + 1); break;
406 case 'k': XFillRectangle (d.display->display, d, TGC, x0, y1, x1 - x0 + 1, y2 - y1); break;
407 case 'l': XFillRectangle (d.display->display, d, TGC, x1, y1, x2 - x1, y2 - y1); break;
314 } 408 }
315 } 409 }
316 410
317 gcv.line_width = 0; 411 gcv.line_width = 0;
318 XChangeGC (DISPLAY, GC, GCLineWidth, &gcv); 412 XChangeGC (d.display->display, TGC, GCLineWidth, &gcv);
413 }
414
415#if ENABLE_COMBINING
416 else if (IS_COMPOSE (t) && (cc = rxvt_composite[t]))
319 } 417 {
418 rxvt_font *f1 = (*fs)[fs->find_font (cc->c1)];
419 f1->draw (d, x, y, &(t = cc->c1), 1, fg, bg);
420 if (cc->c2 != NOCHAR)
421 {
422 // prefer font of first character, for no good reasons
423 rxvt_font *f2 = f1->has_codepoint (cc->c2)
424 ? f1
425 : (*fs)[fs->find_font (cc->c2)];
426
427 f2->draw (d, x, y, &(t = cc->c2), 1, fg, -1);
428 }
429 }
430#endif
320 else 431 else
321 switch (*text++) 432 switch (t)
322 { 433 {
323 case NOCHAR:
324 case ZERO_WIDTH_CHAR: 434 case ZERO_WIDTH_CHAR:
325 break; 435 break;
436
437 case 0x2580: XFillRectangle (d.display->display, d, TGC, x0, y0, W, y1 - y0 + 1); break;
438 case 0x2581: XFillRectangle (d.display->display, d, TGC, x0, y0 + (H * 7 - 1) / 8, W, H - (H * 7 - 1) / 8); break;
439 case 0x2582: XFillRectangle (d.display->display, d, TGC, x0, y0 + (H * 6 - 2) / 8, W, H - (H * 6 - 2) / 8); break;
440 case 0x2583: XFillRectangle (d.display->display, d, TGC, x0, y0 + (H * 5 - 3) / 8, W, H - (H * 5 - 3) / 8); break;
441 case 0x2584: XFillRectangle (d.display->display, d, TGC, x0, y0 + (H * 4 - 4) / 8, W, H - (H * 4 - 4) / 8); break;
442 case 0x2585: XFillRectangle (d.display->display, d, TGC, x0, y0 + (H * 3 - 5) / 8, W, H - (H * 3 - 5) / 8); break;
443 case 0x2586: XFillRectangle (d.display->display, d, TGC, x0, y0 + (H * 2 - 6) / 8, W, H - (H * 2 - 6) / 8); break;
444 case 0x2587: XFillRectangle (d.display->display, d, TGC, x0, y0 + (H * 1 - 7) / 8, W, H - (H * 1 - 7) / 8); break;
445 case 0x2588: XFillRectangle (d.display->display, d, TGC, x0, y0, W, H); break;
446 case 0x2589: XFillRectangle (d.display->display, d, TGC, x0, y0, (W * 7 - 1) / 8, H); break;
447 case 0x258a: XFillRectangle (d.display->display, d, TGC, x0, y0, (W * 6 - 2) / 8, H); break;
448 case 0x258b: XFillRectangle (d.display->display, d, TGC, x0, y0, (W * 5 - 3) / 8, H); break;
449 case 0x258c: XFillRectangle (d.display->display, d, TGC, x0, y0, (W * 4 - 4) / 8, H); break;
450 case 0x258d: XFillRectangle (d.display->display, d, TGC, x0, y0, (W * 3 - 5) / 8, H); break;
451 case 0x258e: XFillRectangle (d.display->display, d, TGC, x0, y0, (W * 2 - 6) / 8, H); break;
452 case 0x258f: XFillRectangle (d.display->display, d, TGC, x0, y0, (W * 1 - 7) / 8, H); break;
453 case 0x2590: XFillRectangle (d.display->display, d, TGC, x1, y0, x2 - x1, H); break;
454
455 case 0x2591: rect_stipple (d.display->display, d, TGC, 0x00, 0x01, x0, y0, W, H); break;
456 case 0x2592: rect_stipple (d.display->display, d, TGC, 0x02, 0x01, x0, y0, W, H); break;
457 case 0x2593: rect_stipple (d.display->display, d, TGC, 0x01, 0x03, x0, y0, W, H); break;
458
459 case 0x2594: XFillRectangle (d.display->display, d, TGC, x0, y0, W, (H * 1 - 7) / 8); break;
460 case 0x2595: XFillRectangle (d.display->display, d, TGC, x0 + (W * 7 - 1) / 8, y0, W - (W * 7 - 1) / 8, H); break;
461
326 default: 462 default:
327 XDrawRectangle (DISPLAY, DRAWABLE, GC, x + 2, y + 2, r->TermWin.fwidth - 5, r->TermWin.fheight - 5); 463 int w = 0;
464 while (len > 0 && *text == NOCHAR)
465 {
466 ++text;
467 --len;
468 w += r->TermWin.fwidth;
469 }
470
471 XDrawRectangle (d.display->display, d, TGC, x + 2, y + 2,
472 w + r->TermWin.fwidth - 4, r->TermWin.fheight - 4);
473 x += w;
328 } 474 }
329 475
330 x += r->TermWin.fwidth; 476 x += r->TermWin.fwidth;
331 } 477 }
332} 478}
337 rxvt_font_x11 () { f = 0; } 483 rxvt_font_x11 () { f = 0; }
338 484
339 void clear (); 485 void clear ();
340 486
341 rxvt_fontprop properties (); 487 rxvt_fontprop properties ();
342 rxvt_fontprop properties (XFontStruct *f);
343 488
344 bool load (const rxvt_fontprop &prop); 489 bool load (const rxvt_fontprop &prop);
345 490
346 bool has_codepoint (uint32_t unicode); 491 bool has_codepoint (unicode_t unicode);
347 492
348 void draw (int x, int y, 493 void draw (rxvt_drawable &d, int x, int y,
349 const text_t *text, int len, 494 const text_t *text, int len,
350 int fg, int bg); 495 int fg, int bg);
351 496
352 XFontStruct *f; 497 XFontStruct *f;
353 codeset cs; 498 codeset cs;
354 bool enc2b, encm; 499 bool enc2b, encm;
355 500
356 const char *get_property (XFontStruct *f, const char *property, const char *repl) const; 501 const char *get_property (XFontStruct *f, const char *property, const char *repl) const;
502 bool set_properties (rxvt_fontprop &p, int height, const char *weight, const char *slant, int avgwidth);
503 bool set_properties (rxvt_fontprop &p, XFontStruct *f);
504 bool set_properties (rxvt_fontprop &p, const char *name);
357}; 505};
358 506
359const char * 507const char *
360rxvt_font_x11::get_property (XFontStruct *f, const char *property, const char *repl) const 508rxvt_font_x11::get_property (XFontStruct *f, const char *property, const char *repl) const
361{ 509{
368} 516}
369 517
370rxvt_fontprop 518rxvt_fontprop
371rxvt_font_x11::properties () 519rxvt_font_x11::properties ()
372{ 520{
373 return properties (f);
374}
375
376rxvt_fontprop
377rxvt_font_x11::properties (XFontStruct *f)
378{
379 rxvt_fontprop p; 521 rxvt_fontprop p;
522 set_properties (p, f);
523 return p;
524}
380 525
526bool
527rxvt_font_x11::set_properties (rxvt_fontprop &p, int height, const char *weight, const char *slant, int avgwidth)
528{
529 p.width = avgwidth ? (avgwidth + 1) / 10 : (height + 1) / 2;
530 p.height = height;
531 p.weight = *weight == 'B' || *weight == 'b' ? rxvt_fontprop::bold : rxvt_fontprop::medium;
532 p.slant = *slant == 'r' || *slant == 'R' ? rxvt_fontprop::roman : rxvt_fontprop::italic;
533
534 return true;
535}
536
537bool
538rxvt_font_x11::set_properties (rxvt_fontprop &p, XFontStruct *f)
539{
381 const char *weight = get_property (f, "WEIGHT_NAME", "medium"); 540 const char *weight = get_property (f, "WEIGHT_NAME", "medium");
382 const char *slant = get_property (f, "SLANT", "r"); 541 const char *slant = get_property (f, "SLANT", "r");
383 542
384 p.height = height; 543 unsigned long height;
385 p.weight = *weight == 'B' || *weight == 'b' ? rxvt_fontprop::bold : rxvt_fontprop::medium; 544 if (!XGetFontProperty (f, XInternAtom (DISPLAY, "PIXEL_SIZE", 0), &height))
386 p.slant = *slant == 'r' || *slant == 'R' ? rxvt_fontprop::roman : rxvt_fontprop::italic; 545 return false;
387 546
388 return p; 547 unsigned long avgwidth;
548 if (!XGetFontProperty (f, XInternAtom (DISPLAY, "AVERAGE_WIDTH", 0), &avgwidth))
549 avgwidth = 0;
550
551 return set_properties (p, height, weight, slant, avgwidth);
552}
553
554bool
555rxvt_font_x11::set_properties (rxvt_fontprop &p, const char *name)
556{
557 int slashes = 0;
558 const char *comp[13];
559
560 for (const char *c = name; *c; c++)
561 if (*c == '-')
562 {
563 comp[slashes++] = c + 1;
564 if (slashes >= 13)
565 break;
566 }
567
568 /* can we short-circuit the costly XLoadQueryFont? */
569 if (slashes >= 13
570 && (*comp[ 6] >= '1' && *comp[ 6] <= '9')
571 && (*comp[11] >= '0' && *comp[11] <= '9'))
572 return set_properties (p, atoi (comp[6]), comp[2], comp[3], atoi (comp[11]));
573
574 XFontStruct *f = XLoadQueryFont (DISPLAY, name);
575
576 if (f)
577 {
578 // the font should really exist now. if not, we have a problem
579 // (e.g. if the user did xset fp rehash just when we were searching fonts).
580 // in that case, just return garbage.
581 bool ret = set_properties (p, f);
582 XFreeFont (DISPLAY, f);
583 return ret;
584 }
585 else
586 return false;
587}
588
589// fix the size of scalable fonts
590static void
591fix_scalable (char *buf, const char *name, const rxvt_fontprop &prop)
592{
593 int slashes = 0;
594 const char *size;
595
596 for (const char *c = name; *c; c++)
597 if (*c == '-')
598 {
599 if (slashes == 6)
600 size = c + 1;
601
602 if (++slashes >= 13)
603 break;
604 }
605
606 if (slashes >= 13 && size[0] == '0')
607 {
608 strncpy (buf, name, size - name);
609 buf += size - name;
610 buf += sprintf (buf, "%d", prop.height);
611 strcpy (buf, size + 1);
612 }
613 else
614 strcpy (buf, name);
389} 615}
390 616
391bool 617bool
392rxvt_font_x11::load (const rxvt_fontprop &prop) 618rxvt_font_x11::load (const rxvt_fontprop &prop)
393{ 619{
394 clear (); 620 clear ();
395 621
396 char **list; 622 char **list;
397 int count; 623 int count;
398 XFontStruct *info;
399 list = XListFontsWithInfo (DISPLAY, name, 128, &count, &info); 624 list = XListFonts (DISPLAY, name, 512, &count);
625 set_name (0);
400 626
401 if (!list) 627 if (!list)
402 return false; 628 return false;
403 629
404 int bestdiff = 0x7fffffff; 630 int bestdiff = 0x7fffffff;
405 XFontStruct *best = 0;
406 for (int i = 0; i < count; i++) 631 for (int i = 0; i < count; i++)
407 { 632 {
408 XFontStruct *f = info + i; 633 rxvt_fontprop p;
634 char fname[1024];
635 fix_scalable (fname, list[i], prop);
409 636
637 if (!set_properties (p, fname))
638 continue;
639
410 if (f->ascent + f->descent <= prop.height) // weed out too large fonts 640 if (p.height > prop.height) // weed out too large fonts
411 { 641 continue;
412 rxvt_fontprop p = properties (f); 642
413 int diff = (prop.height - f->ascent + f->descent) * 32 643 int diff = (prop.height - p.height) * 32
414 + abs (prop.weight - p.weight) 644 + abs (prop.weight - p.weight)
415 + abs (prop.slant - p.slant ); 645 + abs (prop.slant - p.slant );
416 646
417 if (!best // compare against best found so far 647 if (!name // compare against best found so far
418 || diff < bestdiff) 648 || diff < bestdiff)
419 { 649 {
420 best = f; 650 set_name (strdup (fname));
421 bestdiff = diff; 651 bestdiff = diff;
422 } 652 }
423 }
424 } 653 }
425 654
655 XFreeFontNames (list);
656
426 if (!best) 657 if (!name)
427 return false; 658 return false;
428
429 set_name (strdup (list[best - info]));
430
431 XFreeFontInfo (list, info, count);
432 659
433 f = XLoadQueryFont (DISPLAY, name); 660 f = XLoadQueryFont (DISPLAY, name);
434 661
435 if (!f) 662 if (!f)
436 return false; 663 return false;
437
438 unsigned long value;
439 664
440 const char *registry = get_property (f, "CHARSET_REGISTRY", 0); 665 const char *registry = get_property (f, "CHARSET_REGISTRY", 0);
441 const char *encoding = get_property (f, "CHARSET_ENCODING", 0); 666 const char *encoding = get_property (f, "CHARSET_ENCODING", 0);
442 667
443 if (registry && encoding) 668 if (registry && encoding)
518 f = 0; 743 f = 0;
519 } 744 }
520} 745}
521 746
522bool 747bool
523rxvt_font_x11::has_codepoint (uint32_t unicode) 748rxvt_font_x11::has_codepoint (unicode_t unicode)
524{ 749{
525 uint32_t ch = FROM_UNICODE (cs, unicode); 750 uint32_t ch = FROM_UNICODE (cs, unicode);
526 751
527 if (ch == NOCHAR) 752 if (ch == NOCHAR)
528 return false; 753 return false;
530 /* check wether the character exists in _this_ font. horrible. */ 755 /* check wether the character exists in _this_ font. horrible. */
531 XCharStruct *xcs; 756 XCharStruct *xcs;
532 757
533 if (encm) 758 if (encm)
534 { 759 {
535 int byte1 = ch >> 8; 760 unsigned char byte1 = ch >> 8;
536 int byte2 = ch & 255; 761 unsigned char byte2 = ch & 255;
537 762
538 if (byte1 < f->min_byte1 || byte1 > f->max_byte1 763 if (byte1 < f->min_byte1 || byte1 > f->max_byte1
539 || byte2 < f->min_char_or_byte2 || byte2 > f->max_char_or_byte2) 764 || byte2 < f->min_char_or_byte2 || byte2 > f->max_char_or_byte2)
540 return false; 765 return false;
541 766
564 789
565 return true; 790 return true;
566} 791}
567 792
568void 793void
569rxvt_font_x11::draw (int x, int y, 794rxvt_font_x11::draw (rxvt_drawable &d, int x, int y,
570 const text_t *text, int len, 795 const text_t *text, int len,
571 int fg, int bg) 796 int fg, int bg)
572{ 797{
573 // this looks like a mess /. 798 // this looks like a mess /.
574 // and it is a mess /. 799 // and it is a mess /.
590 { 815 {
591 const XChar2b *xc = enc_xchar2b (text, len, cs, slow); 816 const XChar2b *xc = enc_xchar2b (text, len, cs, slow);
592 817
593 if (bg == Color_bg && !slow) 818 if (bg == Color_bg && !slow)
594 { 819 {
595 XChangeGC (DISPLAY, GC, GCForeground | GCBackground | GCFont, &v); 820 XChangeGC (d.display->display, TGC, GCForeground | GCBackground | GCFont, &v);
596 XDrawImageString16 (DISPLAY, DRAWABLE, GC, x, y + base, xc, len); 821 XDrawImageString16 (d.display->display, d, TGC, x, y + base, xc, len);
597 } 822 }
598 else 823 else
599 { 824 {
600 clear_rect (x, y, r->TermWin.fwidth * len, r->TermWin.fheight, bg); 825 clear_rect (d, x, y, r->TermWin.fwidth * len, r->TermWin.fheight, bg);
601 826
602 XChangeGC (DISPLAY, GC, GCForeground | GCFont, &v); 827 XChangeGC (d.display->display, TGC, GCForeground | GCFont, &v);
603 828
604 if (slow) 829 if (slow)
605 { 830 {
606 do 831 do
607 { 832 {
608 if (xc->byte1 || xc->byte2) 833 if (xc->byte1 || xc->byte2)
609 XDrawString16 (DISPLAY, DRAWABLE, GC, x, y + base, xc, 1); 834 XDrawString16 (d.display->display, d, TGC, x, y + base, xc, 1);
610 835
611 x += r->TermWin.fwidth; 836 x += r->TermWin.fwidth;
612 xc++; len--; 837 xc++; len--;
613 } 838 }
614 while (len); 839 while (len);
615 } 840 }
616 else 841 else
617 XDrawString16 (DISPLAY, DRAWABLE, GC, x, y + base, xc, len); 842 XDrawString16 (d.display->display, d, TGC, x, y + base, xc, len);
618 } 843 }
619 } 844 }
620 else 845 else
621 { 846 {
622 const char *xc = enc_char (text, len, cs, slow); 847 const char *xc = enc_char (text, len, cs, slow);
623 848
624 if (bg == Color_bg && !slow) 849 if (bg == Color_bg && !slow)
625 { 850 {
626 XChangeGC (DISPLAY, GC, GCForeground | GCBackground | GCFont, &v); 851 XChangeGC (d.display->display, TGC, GCForeground | GCBackground | GCFont, &v);
627 XDrawImageString (DISPLAY, DRAWABLE, GC, x, y + base, xc, len); 852 XDrawImageString (d.display->display, d, TGC, x, y + base, xc, len);
628 } 853 }
629 else 854 else
630 { 855 {
631 clear_rect (x, y, r->TermWin.fwidth * len, r->TermWin.fheight, bg); 856 clear_rect (d, x, y, r->TermWin.fwidth * len, r->TermWin.fheight, bg);
632 857
633 XChangeGC (DISPLAY, GC, GCForeground | GCFont, &v); 858 XChangeGC (d.display->display, TGC, GCForeground | GCFont, &v);
634 859
635 if (slow) 860 if (slow)
636 { 861 {
637 do 862 do
638 { 863 {
639 if (*xc) 864 if (*xc)
640 XDrawString (DISPLAY, DRAWABLE, GC, x, y + base, xc, 1); 865 XDrawString (d.display->display, d, TGC, x, y + base, xc, 1);
641 866
642 x += r->TermWin.fwidth; 867 x += r->TermWin.fwidth;
643 xc++; len--; 868 xc++; len--;
644 } 869 }
645 while (len); 870 while (len);
646 } 871 }
647 else 872 else
648 XDrawString (DISPLAY, DRAWABLE, GC, x, y + base, xc, len); 873 XDrawString (d.display->display, d, TGC, x, y + base, xc, len);
649 } 874 }
650 } 875 }
651} 876}
652 877
653///////////////////////////////////////////////////////////////////////////// 878/////////////////////////////////////////////////////////////////////////////
658//#define SWATHBITS (UNIBITS / 2 + 3) // minimum size for "full" tables 883//#define SWATHBITS (UNIBITS / 2 + 3) // minimum size for "full" tables
659#define SWATHBITS 8 884#define SWATHBITS 8
660#endif 885#endif
661 886
662struct rxvt_font_xft : rxvt_font { 887struct rxvt_font_xft : rxvt_font {
663#if 0
664 enum {
665 SWATHCOUNT = 1 << (21 - UNIBITS),
666 SWATHSIZE = 1 << (SWATHBITS - 5)
667 };
668 typedef uint32_t swath[SWATHSIZE];
669
670 swath *cvr[SWATHCOUNT];
671#endif
672
673#if 0
674 void gen_coverage_swath (unsigned int page);
675
676 bool has_char (uint32_t ch)
677 {
678 unsigned int page = ch >> SWATHBITS;
679 unsigned int idx = ch & ((1 << SWATHBITS) - 1);
680
681 if (page >= SWATHCOUNT)
682 return false;
683
684 if (!cvr[page]) gen_coverage_swath (page);
685
686 return cvr[page][idx >> 5] & (1 << (idx & 31));
687 }
688#endif
689 rxvt_font_xft () { f = 0; d = 0; } 888 rxvt_font_xft () { f = 0; }
690 889
691 void clear (); 890 void clear ();
692 891
693 rxvt_fontprop properties (); 892 rxvt_fontprop properties ();
694 893
695 bool load (const rxvt_fontprop &prop); 894 bool load (const rxvt_fontprop &prop);
696 895
697 void draw (int x, int y, 896 void draw (rxvt_drawable &d, int x, int y,
698 const text_t *text, int len, 897 const text_t *text, int len,
699 int fg, int bg); 898 int fg, int bg);
700 899
701 bool has_codepoint (uint32_t unicode); 900 bool has_codepoint (unicode_t unicode);
702 901
703protected: 902protected:
704 XftFont *f; 903 XftFont *f;
705 XftDraw *d;
706
707#if 0
708 virtual void populate_coverage_swath (uint32_t lo, uint32_t hi) = 0;
709 void set_swath (uint32_t ch)
710 {
711 cvr[ch >> SWATHBITS] |= 1 << (ch & ((1 << SWATHBITS) - 1));
712 }
713#endif
714}; 904};
715 905
716void 906void
717rxvt_font_xft::clear () 907rxvt_font_xft::clear ()
718{ 908{
719 if (f) 909 if (f)
720 { 910 {
721 XftFontClose (DISPLAY, f); 911 XftFontClose (DISPLAY, f);
722 f = 0; 912 f = 0;
723 } 913 }
724
725 if (d)
726 {
727 XftDrawDestroy (d);
728 d = 0;
729 }
730
731#if 0
732 for (int i = 0; i < SWATHCOUNT; i++)
733 delete cvr[i];
734#endif
735} 914}
736 915
737rxvt_fontprop 916rxvt_fontprop
738rxvt_font_xft::properties () 917rxvt_font_xft::properties ()
739{ 918{
740 rxvt_fontprop p; 919 rxvt_fontprop p;
741 920
742 FT_Face face = XftLockFace (f); 921 FT_Face face = XftLockFace (f);
743 922
744 p.height = height; 923 p.width = width; p.height = height;
745 p.weight = face->style_flags & FT_STYLE_FLAG_BOLD ? rxvt_fontprop::bold : rxvt_fontprop::medium; 924 p.weight = face->style_flags & FT_STYLE_FLAG_BOLD ? rxvt_fontprop::bold : rxvt_fontprop::medium;
746 p.slant = face->style_flags & FT_STYLE_FLAG_ITALIC ? rxvt_fontprop::italic : rxvt_fontprop::roman; 925 p.slant = face->style_flags & FT_STYLE_FLAG_ITALIC ? rxvt_fontprop::italic : rxvt_fontprop::roman;
747 926
748 XftUnlockFace (f); 927 XftUnlockFace (f);
749 928
770 if (FcPatternGet (p, FC_WEIGHT, 0, &v) != FcResultMatch) 949 if (FcPatternGet (p, FC_WEIGHT, 0, &v) != FcResultMatch)
771 FcPatternAddInteger (p, FC_WEIGHT, prop.weight); 950 FcPatternAddInteger (p, FC_WEIGHT, prop.weight);
772 951
773 if (FcPatternGet (p, FC_SLANT, 0, &v) != FcResultMatch) 952 if (FcPatternGet (p, FC_SLANT, 0, &v) != FcResultMatch)
774 FcPatternAddInteger (p, FC_SLANT, prop.slant); 953 FcPatternAddInteger (p, FC_SLANT, prop.slant);
954
955#if 0 // clipping unfortunately destroys our precious double-width-characters
956 // clip width, we can't do better, or can we?
957 if (FcPatternGet (p, FC_CHAR_WIDTH, 0, &v) != FcResultMatch)
958 FcPatternAddInteger (p, FC_CHAR_WIDTH, prop.width);
959#endif
775 960
776 //FcPatternAddBool (p, FC_MINSPACE, 1); 961 //FcPatternAddBool (p, FC_MINSPACE, 1);
777 962
778 XftResult result; 963 XftResult result;
779 FcPattern *match = XftFontMatch (DISPLAY, DefaultScreen (DISPLAY), p, &result); 964 FcPattern *match = XftFontMatch (DISPLAY, DefaultScreen (DISPLAY), p, &result);
832 XftUnlockFace (f); 1017 XftUnlockFace (f);
833 1018
834 return true; 1019 return true;
835} 1020}
836 1021
837#if 0
838void rxvt_font::gen_coverage_swath (unsigned int page)
839{
840 cvr[page] = new swath;
841
842 for (int i = 0; i < SWATHSIZE; i++)
843 cvr[page][i] = 0;
844
845 populate_coverage_swath (cvr[page], page << SWATHBITS, ((page + 1) << SWATHBITS) - 1);
846}
847#endif
848
849bool 1022bool
850rxvt_font_xft::has_codepoint (uint32_t unicode) 1023rxvt_font_xft::has_codepoint (unicode_t unicode)
851{ 1024{
852 return XftCharExists (DISPLAY, f, unicode); 1025 return XftCharExists (DISPLAY, f, unicode);
853} 1026}
854 1027
855void 1028void
856rxvt_font_xft::draw (int x, int y, 1029rxvt_font_xft::draw (rxvt_drawable &d, int x, int y,
857 const text_t *text, int len, 1030 const text_t *text, int len,
858 int fg, int bg) 1031 int fg, int bg)
859{ 1032{
860 if (!d)
861 {
862 dR;
863 d = XftDrawCreate (DISPLAY, DRAWABLE, XVISUAL, XCMAP);
864 }
865
866 if (bg >= 0 && bg != Color_bg)
867 XftDrawRect (d, &r->PixColors[bg].c, x, y, r->TermWin.fwidth * len, r->TermWin.fheight);
868 else
869 clear_rect (x, y, r->TermWin.fwidth * len, r->TermWin.fheight, bg); 1033 clear_rect (d, x, y, r->TermWin.fwidth * len, r->TermWin.fheight, bg);
870 1034
871 if (!slow && width == r->TermWin.fwidth) 1035 if (!slow && width == r->TermWin.fwidth && 0)
872 { 1036 {
873 if (sizeof (text_t) == sizeof (FcChar16)) 1037 if (sizeof (text_t) == sizeof (FcChar16))
874 XftDrawString16 (d, &r->PixColors[fg].c, f, x, y + r->TermWin.fbase, (const FcChar16 *)text, len); 1038 XftDrawString16 (d, &r->PixColors[fg].c, f, x, y + r->TermWin.fbase, (const FcChar16 *)text, len);
875 else 1039 else
876 XftDrawString32 (d, &r->PixColors[fg].c, f, x, y + r->TermWin.fbase, (const FcChar32 *)text, len); 1040 XftDrawString32 (d, &r->PixColors[fg].c, f, x, y + r->TermWin.fbase, (const FcChar32 *)text, len);
879 { 1043 {
880 while (len) 1044 while (len)
881 { 1045 {
882 if (*text != NOCHAR && *text != ' ') 1046 if (*text != NOCHAR && *text != ' ')
883 { 1047 {
1048 int fwidth = r->TermWin.fwidth;
1049 if (len >= 2 && text[1] == NOCHAR)
1050 fwidth *= 2;
1051
1052 XGlyphInfo extents;
884 if (sizeof (text_t) == sizeof (FcChar16)) 1053 if (sizeof (text_t) == sizeof (FcChar16))
885 XftDrawString16 (d, &r->PixColors[fg].c, f, x, y + r->TermWin.fbase, (const FcChar16 *)text, 1); 1054 {
1055 XftTextExtents16 (d.display->display, f, (const FcChar16 *)text, 1, &extents);
1056 XftDrawString16 (d, &r->PixColors[fg].c, f, x + extents.x + (fwidth - extents.width) / 2,
1057 y + r->TermWin.fbase, (const FcChar16 *)text, 1);
1058 }
886 else 1059 else
887 XftDrawString32 (d, &r->PixColors[fg].c, f, x, y + r->TermWin.fbase, (const FcChar32 *)text, 1); 1060 {
1061 XGlyphInfo extents;
1062 XftTextExtents32 (d.display->display, f, (const FcChar32 *)text, 1, &extents);
1063 XftDrawString32 (d, &r->PixColors[fg].c, f, x + extents.x + (fwidth - extents.width) / 2,
1064 y + r->TermWin.fbase, (const FcChar32 *)text, 1);
1065 }
888 } 1066 }
889 1067
890 x += r->TermWin.fwidth; 1068 x += r->TermWin.fwidth;
891 text++; 1069 text++;
892 len--; 1070 len--;
896#endif 1074#endif
897 1075
898///////////////////////////////////////////////////////////////////////////// 1076/////////////////////////////////////////////////////////////////////////////
899 1077
900rxvt_fontset::rxvt_fontset (rxvt_t r) 1078rxvt_fontset::rxvt_fontset (rxvt_t r)
901#ifdef EXPLICIT_CONTEXT
902: r(r) 1079: r (r)
903#endif
904{ 1080{
905 clear (); 1081 clear ();
906} 1082}
907 1083
908rxvt_fontset::~rxvt_fontset () 1084rxvt_fontset::~rxvt_fontset ()
911} 1087}
912 1088
913void 1089void
914rxvt_fontset::clear () 1090rxvt_fontset::clear ()
915{ 1091{
916 for (rxvt_font **i = fonts.begin (); i != fonts.end(); i++) 1092 for (rxvt_font **i = fonts.begin (); i != fonts.end (); i++)
917 FONT_UNREF (*i); 1093 FONT_UNREF (*i);
918 1094
919 fonts.clear (); 1095 fonts.clear ();
920 base_id = 0; 1096 base_id = 0;
921 base_prop.height = 0x7fffffff; 1097 base_prop.height = 0x7fffffff;
948 f = new rxvt_font_x11; 1124 f = new rxvt_font_x11;
949 } 1125 }
950 else 1126 else
951 f = new rxvt_font_x11; 1127 f = new rxvt_font_x11;
952 1128
1129 f->fs = this;
953 f->set_term (r); 1130 f->set_term (r);
954 f->set_name (strdup (name)); 1131 f->set_name (strdup (name));
955 1132
956 f->cs = cs; 1133 f->cs = cs;
957 f->loaded = false; 1134 f->loaded = false;
975 1152
976 if (*desc == '[') 1153 if (*desc == '[')
977 { 1154 {
978 fprintf (stderr, "extra font parameters not yet supported, skipping.\n"); 1155 fprintf (stderr, "extra font parameters not yet supported, skipping.\n");
979 1156
980 const char *extra = desc++; 1157 //const char *extra = desc++; // not yet used
981 1158
982 desc = strchr (desc, ']'); 1159 desc = strchr (desc, ']');
983 1160
984 if (!desc) 1161 if (!desc)
985 { 1162 {
1024 } 1201 }
1025 1202
1026 return true; 1203 return true;
1027} 1204}
1028 1205
1029void 1206bool
1030rxvt_fontset::populate (const char *desc) 1207rxvt_fontset::populate (const char *desc)
1031{ 1208{
1032 clear (); 1209 clear ();
1033 1210
1034 fonts.push_back (new_font (0, CS_UNICODE)); 1211 fonts.push_back (new_font (0, CS_UNICODE));
1038 1215
1039 if (!base_id) 1216 if (!base_id)
1040 base_id = 1; 1217 base_id = 1;
1041 1218
1042 // we currently need a base-font, no matter what 1219 // we currently need a base-font, no matter what
1043 if (fonts.size () <= base_id || !realize_font (base_id)) 1220 if ((int)fonts.size () <= base_id || !realize_font (base_id))
1044 { 1221 {
1222 puts ("unable to load specified font (s), falling back to 'fixed'\n");
1045 add_fonts ("fixed"); 1223 add_fonts ("fixed");
1046 base_id = fonts.size () - 1; 1224 base_id = fonts.size () - 1;
1047 } 1225 }
1048 1226
1049 if (fonts.size () <= base_id || !realize_font (base_id)) 1227 if ((int)fonts.size () <= base_id || !realize_font (base_id))
1050 { 1228 return false;
1051 fprintf (stderr, "unable to load a base font, please provide one using -fn fontname\n");
1052 exit (1);
1053 }
1054 1229
1055 base_prop = fonts[base_id]->properties (); 1230 base_prop = fonts[base_id]->properties ();
1231
1232 return true;
1056} 1233}
1057 1234
1058int 1235int
1059rxvt_fontset::find_font (uint32_t unicode) 1236rxvt_fontset::find_font (unicode_t unicode)
1060{ 1237{
1061 for (int i = 0; i < fonts.size (); i++) 1238 for (unsigned int i = 0; i < fonts.size (); i++)
1062 { 1239 {
1063 rxvt_font *f = fonts[i]; 1240 rxvt_font *f = fonts[i];
1064 1241
1065 if (!f->loaded) 1242 if (!f->loaded)
1066 { 1243 {

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines