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.4 by pcg, Sat Nov 29 18:42:07 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 ();
553
554 char **list;
555 int count;
556 list = XListFonts (DISPLAY, name, 512, &count);
557 set_name (0);
558
559 if (!list)
560 return false;
561
562 int bestdiff = 0x7fffffff;
563 for (int i = 0; i < count; i++)
564 {
565 rxvt_fontprop p;
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
579 if (!name // compare against best found so far
580 || diff < bestdiff)
581 {
582 set_name (strdup (fname));
583 bestdiff = diff;
584 }
585 }
586
587 XFreeFontNames (list);
588
589 if (!name)
590 return false;
357 591
358 f = XLoadQueryFont (DISPLAY, name); 592 f = XLoadQueryFont (DISPLAY, name);
359 593
360 if (!f) 594 if (!f)
361 return false; 595 return false;
362 596
363 unsigned long value;
364
365 const char *registry = get_property ("CHARSET_REGISTRY", 0); 597 const char *registry = get_property (f, "CHARSET_REGISTRY", 0);
366 const char *encoding = get_property ("CHARSET_ENCODING", 0); 598 const char *encoding = get_property (f, "CHARSET_ENCODING", 0);
367 599
368 if (registry && encoding) 600 if (registry && encoding)
369 { 601 {
370 char charset[64]; 602 char charset[64];
371 snprintf (charset, 64, "%s-%s", registry, encoding); 603 snprintf (charset, 64, "%s-%s", registry, encoding);
372 604
373 cs = codeset_from_name (charset); 605 cs = codeset_from_name (charset);
374 } 606 }
375 else 607 else
376 { 608 {
377 const char *charset = get_property ("FONT", 0); 609 const char *charset = get_property (f, "FONT", 0);
378 610
379 if (!charset) 611 if (!charset)
380 charset = name; 612 charset = name;
381 613
382 int count = 13; 614 int count = 13;
395 627
396 ascent = f->ascent; 628 ascent = f->ascent;
397 descent = f->descent; 629 descent = f->descent;
398 height = ascent + descent; 630 height = ascent + descent;
399 631
400 prop = false; 632 slow = false;
401 633
402 if (f->min_bounds.width == f->max_bounds.width) 634 if (f->min_bounds.width == f->max_bounds.width)
403 width = f->min_bounds.width; 635 width = f->min_bounds.width;
404 else if (f->per_char == NULL) 636 else if (f->per_char == NULL)
405 width = f->max_bounds.width; 637 width = f->max_bounds.width;
406 else 638 else
407 { 639 {
408 prop = true; 640 slow = true;
409 641
410 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;
411 643
412 if (encm) 644 if (encm)
413 N += (f->max_byte1 - f->min_byte1) 645 N += (f->max_byte1 - f->min_byte1)
443 f = 0; 675 f = 0;
444 } 676 }
445} 677}
446 678
447bool 679bool
448rxvt_font_x11::has_codepoint (uint32_t unicode) 680rxvt_font_x11::has_codepoint (unicode_t unicode)
449{ 681{
450 uint32_t ch = FROM_UNICODE (cs, unicode); 682 uint32_t ch = FROM_UNICODE (cs, unicode);
451 683
452 if (ch == NOCHAR) 684 if (ch == NOCHAR)
453 return false; 685 return false;
455 /* check wether the character exists in _this_ font. horrible. */ 687 /* check wether the character exists in _this_ font. horrible. */
456 XCharStruct *xcs; 688 XCharStruct *xcs;
457 689
458 if (encm) 690 if (encm)
459 { 691 {
460 int byte1 = ch >> 8; 692 unsigned char byte1 = ch >> 8;
461 int byte2 = ch & 255; 693 unsigned char byte2 = ch & 255;
462 694
463 if (byte1 < f->min_byte1 || byte1 > f->max_byte1 695 if (byte1 < f->min_byte1 || byte1 > f->max_byte1
464 || 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)
465 return false; 697 return false;
466 698
489 721
490 return true; 722 return true;
491} 723}
492 724
493void 725void
494rxvt_font_x11::draw (int x, int y, 726rxvt_font_x11::draw (rxvt_drawable &d, int x, int y,
495 const text_t *text, int len, 727 const text_t *text, int len,
496 int fg, int bg) 728 int fg, int bg)
497{ 729{
498 // this looks like a mess /. 730 // this looks like a mess /.
499 // and it is a mess /. 731 // and it is a mess /.
500 // yet we are trying to be perfect /. 732 // yet we are trying to be perfect /.
501 // but the result still isn't perfect /. 733 // but the result still isn't perfect /.
502 734
503 bool slow = prop 735 bool slow = this->slow
504 || width != r->TermWin.fwidth 736 || width != r->TermWin.fwidth
505 || height != r->TermWin.fheight; 737 || height != r->TermWin.fheight;
506 738
507 int base = r->TermWin.fbase; 739 int base = r->TermWin.fbase;
508 740
515 { 747 {
516 const XChar2b *xc = enc_xchar2b (text, len, cs, slow); 748 const XChar2b *xc = enc_xchar2b (text, len, cs, slow);
517 749
518 if (bg == Color_bg && !slow) 750 if (bg == Color_bg && !slow)
519 { 751 {
520 XChangeGC (DISPLAY, GC, GCForeground | GCBackground | GCFont, &v); 752 XChangeGC (d.display->display, GC, GCForeground | GCBackground | GCFont, &v);
521 XDrawImageString16 (DISPLAY, DRAWABLE, GC, x, y + base, xc, len); 753 XDrawImageString16 (d.display->display, d, GC, x, y + base, xc, len);
522 } 754 }
523 else 755 else
524 { 756 {
525 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);
526 758
527 XChangeGC (DISPLAY, GC, GCForeground | GCFont, &v); 759 XChangeGC (d.display->display, GC, GCForeground | GCFont, &v);
528 760
529 if (slow) 761 if (slow)
530 { 762 {
531 do 763 do
532 { 764 {
533 if (xc->byte1 || xc->byte2) 765 if (xc->byte1 || xc->byte2)
534 XDrawString16 (DISPLAY, DRAWABLE, GC, x, y + base, xc, 1); 766 XDrawString16 (d.display->display, d, GC, x, y + base, xc, 1);
535 767
536 x += r->TermWin.fwidth; 768 x += r->TermWin.fwidth;
537 xc++; len--; 769 xc++; len--;
538 } 770 }
539 while (len); 771 while (len);
540 } 772 }
541 else 773 else
542 XDrawString16 (DISPLAY, DRAWABLE, GC, x, y + base, xc, len); 774 XDrawString16 (d.display->display, d, GC, x, y + base, xc, len);
543 } 775 }
544 } 776 }
545 else 777 else
546 { 778 {
547 const char *xc = enc_char (text, len, cs, slow); 779 const char *xc = enc_char (text, len, cs, slow);
548 780
549 if (bg == Color_bg && !slow) 781 if (bg == Color_bg && !slow)
550 { 782 {
551 XChangeGC (DISPLAY, GC, GCForeground | GCBackground | GCFont, &v); 783 XChangeGC (d.display->display, GC, GCForeground | GCBackground | GCFont, &v);
552 XDrawImageString (DISPLAY, DRAWABLE, GC, x, y + base, xc, len); 784 XDrawImageString (d.display->display, d, GC, x, y + base, xc, len);
553 } 785 }
554 else 786 else
555 { 787 {
556 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);
557 789
558 XChangeGC (DISPLAY, GC, GCForeground | GCFont, &v); 790 XChangeGC (d.display->display, GC, GCForeground | GCFont, &v);
559 791
560 if (slow) 792 if (slow)
561 { 793 {
562 do 794 do
563 { 795 {
564 if (*xc) 796 if (*xc)
565 XDrawString (DISPLAY, DRAWABLE, GC, x, y + base, xc, 1); 797 XDrawString (d.display->display, d, GC, x, y + base, xc, 1);
566 798
567 x += r->TermWin.fwidth; 799 x += r->TermWin.fwidth;
568 xc++; len--; 800 xc++; len--;
569 } 801 }
570 while (len); 802 while (len);
571 } 803 }
572 else 804 else
573 XDrawString (DISPLAY, DRAWABLE, GC, x, y + base, xc, len); 805 XDrawString (d.display->display, d, GC, x, y + base, xc, len);
574 } 806 }
575 } 807 }
576} 808}
577 809
578///////////////////////////////////////////////////////////////////////////// 810/////////////////////////////////////////////////////////////////////////////
583//#define SWATHBITS (UNIBITS / 2 + 3) // minimum size for "full" tables 815//#define SWATHBITS (UNIBITS / 2 + 3) // minimum size for "full" tables
584#define SWATHBITS 8 816#define SWATHBITS 8
585#endif 817#endif
586 818
587struct rxvt_font_xft : rxvt_font { 819struct rxvt_font_xft : rxvt_font {
588#if 0
589 enum {
590 SWATHCOUNT = 1 << (21 - UNIBITS),
591 SWATHSIZE = 1 << (SWATHBITS - 5)
592 };
593 typedef uint32_t swath[SWATHSIZE];
594
595 swath *cvr[SWATHCOUNT];
596#endif
597
598#if 0
599 void gen_coverage_swath (unsigned int page);
600
601 bool has_char (uint32_t ch)
602 {
603 unsigned int page = ch >> SWATHBITS;
604 unsigned int idx = ch & ((1 << SWATHBITS) - 1);
605
606 if (page >= SWATHCOUNT)
607 return false;
608
609 if (!cvr[page]) gen_coverage_swath (page);
610
611 return cvr[page][idx >> 5] & (1 << (idx & 31));
612 }
613#endif
614 rxvt_font_xft () { f = 0; d = 0; } 820 rxvt_font_xft () { f = 0; }
615 821
616 void clear (); 822 void clear ();
617 823
618 bool load (int maxheight); 824 rxvt_fontprop properties ();
619 825
620 void draw (int x, int y, 826 bool load (const rxvt_fontprop &prop);
827
828 void draw (rxvt_drawable &d, int x, int y,
621 const text_t *text, int len, 829 const text_t *text, int len,
622 int fg, int bg); 830 int fg, int bg);
623 831
624 bool has_codepoint (uint32_t unicode); 832 bool has_codepoint (unicode_t unicode);
625 833
626protected: 834protected:
627 XftFont *f; 835 XftFont *f;
628 XftDraw *d;
629
630#if 0
631 virtual void populate_coverage_swath (uint32_t lo, uint32_t hi) = 0;
632 void set_swath (uint32_t ch)
633 {
634 cvr[ch >> SWATHBITS] |= 1 << (ch & ((1 << SWATHBITS) - 1));
635 }
636#endif
637}; 836};
638 837
639void 838void
640rxvt_font_xft::clear () 839rxvt_font_xft::clear ()
641{ 840{
642 if (f) 841 if (f)
643 { 842 {
644 XftFontClose (DISPLAY, f); 843 XftFontClose (DISPLAY, f);
645 f = 0; 844 f = 0;
646 } 845 }
846}
647 847
648 if (d) 848rxvt_fontprop
649 { 849rxvt_font_xft::properties ()
650 XftDrawDestroy (d); 850{
651 d = 0; 851 rxvt_fontprop p;
652 }
653 852
654#if 0 853 FT_Face face = XftLockFace (f);
655 for (int i = 0; i < SWATHCOUNT; i++) 854
656 delete cvr[i]; 855 p.width = width; p.height = height;
657#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;
658} 862}
659 863
660bool 864bool
661rxvt_font_xft::load (int maxheight) 865rxvt_font_xft::load (const rxvt_fontprop &prop)
662{ 866{
663#if 0 867#if 0
664 for (int i = 0; i < SWATHCOUNT; i++) 868 for (int i = 0; i < SWATHCOUNT; i++)
665 cvr[i] = 0; 869 cvr[i] = 0;
666#endif 870#endif
667 871
668 clear (); 872 clear ();
669 873
670 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);
671 904
672 if (!f) 905 if (!f)
906 {
907 FcPatternDestroy (match);
673 return false; 908 return false;
909 }
674 910
675 FT_Face face = XftLockFace (f); 911 FT_Face face = XftLockFace (f);
676 912
677 prop = !FT_IS_FIXED_WIDTH (face); 913 slow = !FT_IS_FIXED_WIDTH (face);
678 914
679 int ftheight = 0; 915 int ftheight = 0;
680 916
681 for (;;) 917 for (;;)
682 { 918 {
684 FcChar8 c; 920 FcChar8 c;
685 921
686 c = 'i'; XftTextExtents8 (DISPLAY, f, &c, 1, &g1); 922 c = 'i'; XftTextExtents8 (DISPLAY, f, &c, 1, &g1);
687 c = 'W'; XftTextExtents8 (DISPLAY, f, &c, 1, &g2); 923 c = 'W'; XftTextExtents8 (DISPLAY, f, &c, 1, &g2);
688 924
689 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;
690 927
691 width = g2.xOff; 928 width = g2.xOff;
692 ascent = (face->size->metrics.ascender + 63) >> 6; 929 ascent = (face->size->metrics.ascender + 63) >> 6;
693 descent = (-face->size->metrics.descender + 63) >> 6; 930 descent = (-face->size->metrics.descender + 63) >> 6;
694 height = ascent + descent; 931 height = ascent + descent;
695 932
696 if (height <= maxheight || !maxheight) 933 if (height <= prop.height || !prop.height)
697 break; 934 break;
698 935
699 if (ftheight) 936 if (ftheight)
700 { 937 {
701 // take smaller steps near the end 938 // take smaller steps near the end
702 if (height > maxheight + 1) ftheight++; 939 if (height > prop.height + 1) ftheight++;
703 if (height > maxheight + 2) ftheight++; 940 if (height > prop.height + 2) ftheight++;
704 if (height > maxheight + 3) ftheight++; 941 if (height > prop.height + 3) ftheight++;
705 942
706 FT_Set_Pixel_Sizes (face, 0, ftheight -= height - maxheight); 943 FT_Set_Pixel_Sizes (face, 0, ftheight -= height - prop.height);
707 } 944 }
708 else 945 else
709 FT_Set_Pixel_Sizes (face, 0, ftheight = maxheight); 946 FT_Set_Pixel_Sizes (face, 0, ftheight = prop.height);
710 } 947 }
711 948
712 XftUnlockFace (f); 949 XftUnlockFace (f);
713 950
714 return true; 951 return true;
715} 952}
716 953
717#if 0
718void rxvt_font::gen_coverage_swath (unsigned int page)
719{
720 cvr[page] = new swath;
721
722 for (int i = 0; i < SWATHSIZE; i++)
723 cvr[page][i] = 0;
724
725 populate_coverage_swath (cvr[page], page << SWATHBITS, ((page + 1) << SWATHBITS) - 1);
726}
727#endif
728
729bool 954bool
730rxvt_font_xft::has_codepoint (uint32_t unicode) 955rxvt_font_xft::has_codepoint (unicode_t unicode)
731{ 956{
732 return XftCharExists (DISPLAY, f, unicode); 957 return XftCharExists (DISPLAY, f, unicode);
733} 958}
734 959
735void 960void
736rxvt_font_xft::draw (int x, int y, 961rxvt_font_xft::draw (rxvt_drawable &d, int x, int y,
737 const text_t *text, int len, 962 const text_t *text, int len,
738 int fg, int bg) 963 int fg, int bg)
739{ 964{
740 if (!d)
741 {
742 dR;
743 d = XftDrawCreate (DISPLAY, DRAWABLE, XVISUAL, XCMAP);
744 }
745
746 if (bg >= 0 && bg != Color_bg)
747 XftDrawRect (d, &r->PixColors[bg].c, x, y, r->TermWin.fwidth * len, r->TermWin.fheight);
748 else
749 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);
750 966
751 if (!prop && width == r->TermWin.fwidth) 967 if (!slow && width == r->TermWin.fwidth && 0)
752 { 968 {
753 if (sizeof (text_t) == sizeof (FcChar16)) 969 if (sizeof (text_t) == sizeof (FcChar16))
754 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);
755 else 971 else
756 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);
759 { 975 {
760 while (len) 976 while (len)
761 { 977 {
762 if (*text != NOCHAR && *text != ' ') 978 if (*text != NOCHAR && *text != ' ')
763 { 979 {
980 int fwidth = r->TermWin.fwidth;
981 if (len >= 2 && text[1] == NOCHAR)
982 fwidth *= 2;
983
984 XGlyphInfo extents;
764 if (sizeof (text_t) == sizeof (FcChar16)) 985 if (sizeof (text_t) == sizeof (FcChar16))
765 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 }
766 else 991 else
767 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 }
768 } 998 }
769 999
770 x += r->TermWin.fwidth; 1000 x += r->TermWin.fwidth;
771 text++; 1001 text++;
772 len--; 1002 len--;
776#endif 1006#endif
777 1007
778///////////////////////////////////////////////////////////////////////////// 1008/////////////////////////////////////////////////////////////////////////////
779 1009
780rxvt_fontset::rxvt_fontset (rxvt_t r) 1010rxvt_fontset::rxvt_fontset (rxvt_t r)
781#ifdef EXPLICIT_CONTEXT
782: r(r) 1011: r (r)
783#endif
784{ 1012{
785 clear (); 1013 clear ();
786} 1014}
787 1015
788rxvt_fontset::~rxvt_fontset () 1016rxvt_fontset::~rxvt_fontset ()
791} 1019}
792 1020
793void 1021void
794rxvt_fontset::clear () 1022rxvt_fontset::clear ()
795{ 1023{
796 for (rxvt_font **i = fonts.begin (); i != fonts.end(); i++) 1024 for (rxvt_font **i = fonts.begin (); i != fonts.end (); i++)
797 FONT_UNREF (*i); 1025 FONT_UNREF (*i);
798 1026
799 fonts.clear (); 1027 fonts.clear ();
800 base_id = 0; 1028 base_id = 0;
801 height = 0x7fffffff; 1029 base_prop.height = 0x7fffffff;
1030 base_prop.weight = rxvt_fontprop::medium;
1031 base_prop.slant = rxvt_fontprop::roman;
802 1032
803 fallback = fallback_fonts; 1033 fallback = fallback_fonts;
804} 1034}
805 1035
806rxvt_font * 1036rxvt_font *
826 f = new rxvt_font_x11; 1056 f = new rxvt_font_x11;
827 } 1057 }
828 else 1058 else
829 f = new rxvt_font_x11; 1059 f = new rxvt_font_x11;
830 1060
1061 f->fs = this;
831 f->set_term (r); 1062 f->set_term (r);
832 f->set_name (strdup (name)); 1063 f->set_name (strdup (name));
833 1064
834 f->cs = cs; 1065 f->cs = cs;
835 f->loaded = false; 1066 f->loaded = false;
853 1084
854 if (*desc == '[') 1085 if (*desc == '[')
855 { 1086 {
856 fprintf (stderr, "extra font parameters not yet supported, skipping.\n"); 1087 fprintf (stderr, "extra font parameters not yet supported, skipping.\n");
857 1088
858 const char *extra = desc++; 1089 //const char *extra = desc++; // not yet used
859 1090
860 desc = strchr (desc, ']'); 1091 desc = strchr (desc, ']');
861 1092
862 if (!desc) 1093 if (!desc)
863 { 1094 {
891rxvt_fontset::realize_font (int i) 1122rxvt_fontset::realize_font (int i)
892{ 1123{
893 if (fonts[i]->loaded) 1124 if (fonts[i]->loaded)
894 return true; 1125 return true;
895 1126
896 if (fonts[i]->load (height))
897 return fonts[i]->loaded = true; 1127 fonts[i]->loaded = true;
898 1128
899 delete fonts[i]; 1129 if (!fonts[i]->load (base_prop))
900 fonts.erase (fonts.begin () + i); 1130 {
901 1131 fonts[i]->cs = CS_UNKNOWN;
902 return false; 1132 return false;
903} 1133 }
904 1134
905void 1135 return true;
1136}
1137
1138bool
906rxvt_fontset::populate (const char *desc) 1139rxvt_fontset::populate (const char *desc)
907{ 1140{
908 clear (); 1141 clear ();
909 1142
910 fonts.push_back (new_font (0, CS_UNICODE)); 1143 fonts.push_back (new_font (0, CS_UNICODE));
914 1147
915 if (!base_id) 1148 if (!base_id)
916 base_id = 1; 1149 base_id = 1;
917 1150
918 // we currently need a base-font, no matter what 1151 // we currently need a base-font, no matter what
919 if (fonts.size () <= base_id) 1152 if ((int)fonts.size () <= base_id || !realize_font (base_id))
920 { 1153 {
1154 puts ("unable to load specified font (s), falling back to 'fixed'\n");
921 add_fonts ("fixed"); 1155 add_fonts ("fixed");
922 base_id = 1; 1156 base_id = fonts.size () - 1;
923 } 1157 }
924 1158
925 if (fonts.size () <= base_id || !realize_font (base_id)) 1159 if ((int)fonts.size () <= base_id || !realize_font (base_id))
926 { 1160 return false;
927 fprintf (stderr, "unable to load a base font, please provide one using -fn fontname\n");
928 exit (1);
929 }
930 1161
931 height = fonts[base_id]->height; 1162 base_prop = fonts[base_id]->properties ();
932 1163
933 /*add_fonts ("-efont-fixed-medium-r-normal-*-14-*-*-*-*-*-iso10646-1,"*/ 1164 return true;
934} 1165}
935 1166
936int 1167int
937rxvt_fontset::find_font (uint32_t unicode) 1168rxvt_fontset::find_font (unicode_t unicode)
938{ 1169{
939 for (int i = 0; i < fonts.size (); i++) 1170 for (unsigned int i = 0; i < fonts.size (); i++)
940 { 1171 {
941 rxvt_font *f = fonts[i]; 1172 rxvt_font *f = fonts[i];
942 1173
943 if (!f->loaded) 1174 if (!f->loaded)
944 { 1175 {
945 if (FROM_UNICODE (f->cs, unicode) == NOCHAR) 1176 if (FROM_UNICODE (f->cs, unicode) == NOCHAR)
946 goto next_font; 1177 goto next_font;
947 1178
948 if (!realize_font (i)) 1179 if (!realize_font (i))
949 {
950 --i;
951 goto next_font; 1180 goto next_font;
952 } 1181 }
953 1182
954 //printf ("added font %s for %04lx\n", f->name, unicode);
955 }
956
957 if (f->has_codepoint (unicode)) 1183 if (f->cs != CS_UNKNOWN && f->has_codepoint (unicode))
958 return i; 1184 return i;
959 1185
960 next_font: 1186 next_font:
961 if (i == fonts.size () - 1 && fallback->name) 1187 if (i == fonts.size () - 1 && fallback->name)
962 { 1188 {
963 fonts.push_back (new_font (fallback->name, fallback->cs)); 1189 fonts.push_back (new_font (fallback->name, fallback->cs));
964 fallback++; 1190 fallback++;
1191 i = 0;
965 } 1192 }
966 } 1193 }
967 1194
968 return 0; /* we must return SOME font */ 1195 return 0; /* we must return SOME font */
969} 1196}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines