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.10 by pcg, Wed Dec 24 09:07:01 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
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 GC 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;
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, GC, r->PixColors[color]);
172 XFillRectangle (DISPLAY, DRAWABLE, GC, x, y, w, h); 200 XFillRectangle (d.display->display, d, GC, x, y, w, h);
201#endif
173 } 202 }
174} 203}
175 204
176static const char *linedraw_cmds[128] = { 205static const char *linedraw_cmds[128] = {
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"
223 252
224 // to be done 253 // to be done
239 bool load (const rxvt_fontprop &prop) 268 bool load (const rxvt_fontprop &prop)
240 { 269 {
241 width = 1; height = 1; 270 width = 1; height = 1;
242 ascent = 1; descent = 0; 271 ascent = 1; descent = 0;
243 272
273 set_name ("built-in pseudofont");
274
244 return true; 275 return true;
245 } 276 }
246 277
247 bool has_codepoint (uint32_t unicode) 278 bool has_codepoint (unicode_t unicode)
248 { 279 {
249 if (unicode <= 0x001f) 280 if (unicode <= 0x001f)
250 return true; 281 return true;
282
251 if (unicode >= 0x0080 && unicode <= 0x009f) 283 if (unicode >= 0x0080 && unicode <= 0x009f)
252 return true; 284 return true;
253 285
254 if (unicode >= 0x2500 && unicode <= 0x257f 286 if (unicode >= 0x2500 && unicode <= 0x257f
255 && linedraw_cmds[unicode - 0x2500]) 287 && linedraw_cmds[unicode - 0x2500])
288 return true;
289
290 if (IS_COMPOSE (unicode))
256 return true; 291 return true;
257 292
258 switch (unicode) 293 switch (unicode)
259 { 294 {
260 case ZERO_WIDTH_CHAR: 295 case ZERO_WIDTH_CHAR:
262 } 297 }
263 298
264 return false; 299 return false;
265 } 300 }
266 301
267 void draw (int x, int y, 302 void draw (rxvt_drawable &d, int x, int y,
268 const text_t *text, int len, 303 const text_t *text, int len,
269 int fg, int bg); 304 int fg, int bg);
270}; 305};
271 306
272void 307void
273rxvt_font_default::draw (int x, int y, 308rxvt_font_default::draw (rxvt_drawable &d, int x, int y,
274 const text_t *text, int len, 309 const text_t *text, int len,
275 int fg, int bg) 310 int fg, int bg)
276{ 311{
277 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);
278 313
279 XSetForeground (DISPLAY, GC, r->PixColors[fg]); 314 XSetForeground (d.display->display, GC, r->PixColors[fg]);
280 315
281 while (len--) 316 while (len--)
282 { 317 {
318#if ENABLE_COMBINING
319 compose_char *cc;
320#endif
283 text_t t = *text++; 321 text_t t = *text++;
284 322
323 // is it in our linedrawing table?
285 if (t >= 0x2500 & t <= 0x2580 && linedraw_cmds[t - 0x2500]) 324 if (t >= 0x2500 & t <= 0x2580 && linedraw_cmds[t - 0x2500])
286 { 325 {
287 const char *p = linedraw_cmds[t - 0x2500]; 326 const char *p = linedraw_cmds[t - 0x2500];
288 327
289 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 ;
290 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;
291 332
292 XGCValues gcv; 333 XGCValues gcv;
334
335 gcv.cap_style = CapNotLast;
336 XChangeGC (d.display->display, GC, GCCapStyle, &gcv);
293 337
294 while (*p) 338 while (*p)
295 { 339 {
296 switch (*p++) 340 switch (*p++)
297 { 341 {
298 case '1': 342 case '1':
299 gcv.line_width = 0; 343 gcv.line_width = 0;
300 XChangeGC (DISPLAY, GC, GCLineWidth, &gcv); 344 XChangeGC (d.display->display, GC, GCLineWidth, &gcv);
301 break; 345 break;
302 346
303 case '2': 347 case '2':
304 gcv.line_width = 2; 348 gcv.line_width = 3;
305 XChangeGC (DISPLAY, GC, GCLineWidth, &gcv); 349 XChangeGC (d.display->display, GC, GCLineWidth, &gcv);
306 break; 350 break;
307 351
308 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;
309 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;
310 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;
311 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
312 case 'a': XDrawLine (DISPLAY, DRAWABLE, GC, x0, y2, x2, y0); break; 359 case '/' : XDrawLine (d.display->display, d, GC, x0, y2, x2 , y0 ); break;
313 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;
314 } 366 }
315 } 367 }
316 368
317 gcv.line_width = 0; 369 gcv.line_width = 0;
318 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]))
319 } 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
320 else 389 else
321 switch (*text++) 390 switch (t)
322 { 391 {
323 case NOCHAR:
324 case ZERO_WIDTH_CHAR: 392 case ZERO_WIDTH_CHAR:
325 break; 393 break;
326 default: 394 default:
327 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;
328 } 406 }
329 407
330 x += r->TermWin.fwidth; 408 x += r->TermWin.fwidth;
331 } 409 }
332} 410}
337 rxvt_font_x11 () { f = 0; } 415 rxvt_font_x11 () { f = 0; }
338 416
339 void clear (); 417 void clear ();
340 418
341 rxvt_fontprop properties (); 419 rxvt_fontprop properties ();
342 rxvt_fontprop properties (XFontStruct *f);
343 420
344 bool load (const rxvt_fontprop &prop); 421 bool load (const rxvt_fontprop &prop);
345 422
346 bool has_codepoint (uint32_t unicode); 423 bool has_codepoint (unicode_t unicode);
347 424
348 void draw (int x, int y, 425 void draw (rxvt_drawable &d, int x, int y,
349 const text_t *text, int len, 426 const text_t *text, int len,
350 int fg, int bg); 427 int fg, int bg);
351 428
352 XFontStruct *f; 429 XFontStruct *f;
353 codeset cs; 430 codeset cs;
354 bool enc2b, encm; 431 bool enc2b, encm;
355 432
356 const char *get_property (XFontStruct *f, 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);
357}; 437};
358 438
359const char * 439const char *
360rxvt_font_x11::get_property (XFontStruct *f, const char *property, const char *repl) const 440rxvt_font_x11::get_property (XFontStruct *f, const char *property, const char *repl) const
361{ 441{
368} 448}
369 449
370rxvt_fontprop 450rxvt_fontprop
371rxvt_font_x11::properties () 451rxvt_font_x11::properties ()
372{ 452{
373 return properties (f);
374}
375
376rxvt_fontprop
377rxvt_font_x11::properties (XFontStruct *f)
378{
379 rxvt_fontprop p; 453 rxvt_fontprop p;
454 set_properties (p, f);
455 return p;
456}
380 457
458bool
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{
381 const char *weight = get_property (f, "WEIGHT_NAME", "medium"); 472 const char *weight = get_property (f, "WEIGHT_NAME", "medium");
382 const char *slant = get_property (f, "SLANT", "r"); 473 const char *slant = get_property (f, "SLANT", "r");
383 474
475 unsigned long height;
476 if (!XGetFontProperty (f, XInternAtom (DISPLAY, "PIXEL_SIZE", 0), &height))
477 return false;
478
384 unsigned long avgwidth; 479 unsigned long avgwidth;
385 p.width = XGetFontProperty (f, XInternAtom (DISPLAY, "AVERAGE_WIDTH", 0), &avgwidth) 480 if (!XGetFontProperty (f, XInternAtom (DISPLAY, "AVERAGE_WIDTH", 0), &avgwidth))
386 ? avgwidth / 10 481 avgwidth = 0;
387 : (height + 1) / 2;
388 p.height = height;
389 p.weight = *weight == 'B' || *weight == 'b' ? rxvt_fontprop::bold : rxvt_fontprop::medium;
390 p.slant = *slant == 'r' || *slant == 'R' ? rxvt_fontprop::roman : rxvt_fontprop::italic;
391 482
392 return p; 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);
393} 547}
394 548
395bool 549bool
396rxvt_font_x11::load (const rxvt_fontprop &prop) 550rxvt_font_x11::load (const rxvt_fontprop &prop)
397{ 551{
398 clear (); 552 clear ();
399 553
400 char **list; 554 char **list;
401 int count; 555 int count;
402 XFontStruct *info;
403 list = XListFontsWithInfo (DISPLAY, name, 128, &count, &info); 556 list = XListFonts (DISPLAY, name, 512, &count);
557 set_name (0);
404 558
405 if (!list) 559 if (!list)
406 return false; 560 return false;
407 561
408 int bestdiff = 0x7fffffff; 562 int bestdiff = 0x7fffffff;
409 XFontStruct *best = 0;
410 for (int i = 0; i < count; i++) 563 for (int i = 0; i < count; i++)
411 { 564 {
412 XFontStruct *f = info + i; 565 rxvt_fontprop p;
566 char fname[1024];
567 fix_scalable (fname, list[i], prop);
413 568
569 if (!set_properties (p, fname))
570 continue;
571
414 if (f->ascent + f->descent <= prop.height) // weed out too large fonts 572 if (p.height > prop.height) // weed out too large fonts
415 { 573 continue;
416 rxvt_fontprop p = properties (f); 574
417 int diff = (prop.height - f->ascent + f->descent) * 32 575 int diff = (prop.height - p.height) * 32
418 + abs (prop.weight - p.weight) 576 + abs (prop.weight - p.weight)
419 + abs (prop.slant - p.slant ); 577 + abs (prop.slant - p.slant );
420 578
421 if (!best // compare against best found so far 579 if (!name // compare against best found so far
422 || diff < bestdiff) 580 || diff < bestdiff)
423 { 581 {
424 best = f; 582 set_name (strdup (fname));
425 bestdiff = diff; 583 bestdiff = diff;
426 } 584 }
427 }
428 } 585 }
429 586
587 XFreeFontNames (list);
588
430 if (!best) 589 if (!name)
431 return false; 590 return false;
432
433 set_name (strdup (list[best - info]));
434
435 XFreeFontInfo (list, info, count);
436 591
437 f = XLoadQueryFont (DISPLAY, name); 592 f = XLoadQueryFont (DISPLAY, name);
438 593
439 if (!f) 594 if (!f)
440 return false; 595 return false;
441
442 unsigned long value;
443 596
444 const char *registry = get_property (f, "CHARSET_REGISTRY", 0); 597 const char *registry = get_property (f, "CHARSET_REGISTRY", 0);
445 const char *encoding = get_property (f, "CHARSET_ENCODING", 0); 598 const char *encoding = get_property (f, "CHARSET_ENCODING", 0);
446 599
447 if (registry && encoding) 600 if (registry && encoding)
522 f = 0; 675 f = 0;
523 } 676 }
524} 677}
525 678
526bool 679bool
527rxvt_font_x11::has_codepoint (uint32_t unicode) 680rxvt_font_x11::has_codepoint (unicode_t unicode)
528{ 681{
529 uint32_t ch = FROM_UNICODE (cs, unicode); 682 uint32_t ch = FROM_UNICODE (cs, unicode);
530 683
531 if (ch == NOCHAR) 684 if (ch == NOCHAR)
532 return false; 685 return false;
534 /* check wether the character exists in _this_ font. horrible. */ 687 /* check wether the character exists in _this_ font. horrible. */
535 XCharStruct *xcs; 688 XCharStruct *xcs;
536 689
537 if (encm) 690 if (encm)
538 { 691 {
539 int byte1 = ch >> 8; 692 unsigned char byte1 = ch >> 8;
540 int byte2 = ch & 255; 693 unsigned char byte2 = ch & 255;
541 694
542 if (byte1 < f->min_byte1 || byte1 > f->max_byte1 695 if (byte1 < f->min_byte1 || byte1 > f->max_byte1
543 || 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)
544 return false; 697 return false;
545 698
568 721
569 return true; 722 return true;
570} 723}
571 724
572void 725void
573rxvt_font_x11::draw (int x, int y, 726rxvt_font_x11::draw (rxvt_drawable &d, int x, int y,
574 const text_t *text, int len, 727 const text_t *text, int len,
575 int fg, int bg) 728 int fg, int bg)
576{ 729{
577 // this looks like a mess /. 730 // this looks like a mess /.
578 // and it is a mess /. 731 // and it is a mess /.
594 { 747 {
595 const XChar2b *xc = enc_xchar2b (text, len, cs, slow); 748 const XChar2b *xc = enc_xchar2b (text, len, cs, slow);
596 749
597 if (bg == Color_bg && !slow) 750 if (bg == Color_bg && !slow)
598 { 751 {
599 XChangeGC (DISPLAY, GC, GCForeground | GCBackground | GCFont, &v); 752 XChangeGC (d.display->display, GC, GCForeground | GCBackground | GCFont, &v);
600 XDrawImageString16 (DISPLAY, DRAWABLE, GC, x, y + base, xc, len); 753 XDrawImageString16 (d.display->display, d, GC, x, y + base, xc, len);
601 } 754 }
602 else 755 else
603 { 756 {
604 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);
605 758
606 XChangeGC (DISPLAY, GC, GCForeground | GCFont, &v); 759 XChangeGC (d.display->display, GC, GCForeground | GCFont, &v);
607 760
608 if (slow) 761 if (slow)
609 { 762 {
610 do 763 do
611 { 764 {
612 if (xc->byte1 || xc->byte2) 765 if (xc->byte1 || xc->byte2)
613 XDrawString16 (DISPLAY, DRAWABLE, GC, x, y + base, xc, 1); 766 XDrawString16 (d.display->display, d, GC, x, y + base, xc, 1);
614 767
615 x += r->TermWin.fwidth; 768 x += r->TermWin.fwidth;
616 xc++; len--; 769 xc++; len--;
617 } 770 }
618 while (len); 771 while (len);
619 } 772 }
620 else 773 else
621 XDrawString16 (DISPLAY, DRAWABLE, GC, x, y + base, xc, len); 774 XDrawString16 (d.display->display, d, GC, x, y + base, xc, len);
622 } 775 }
623 } 776 }
624 else 777 else
625 { 778 {
626 const char *xc = enc_char (text, len, cs, slow); 779 const char *xc = enc_char (text, len, cs, slow);
627 780
628 if (bg == Color_bg && !slow) 781 if (bg == Color_bg && !slow)
629 { 782 {
630 XChangeGC (DISPLAY, GC, GCForeground | GCBackground | GCFont, &v); 783 XChangeGC (d.display->display, GC, GCForeground | GCBackground | GCFont, &v);
631 XDrawImageString (DISPLAY, DRAWABLE, GC, x, y + base, xc, len); 784 XDrawImageString (d.display->display, d, GC, x, y + base, xc, len);
632 } 785 }
633 else 786 else
634 { 787 {
635 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);
636 789
637 XChangeGC (DISPLAY, GC, GCForeground | GCFont, &v); 790 XChangeGC (d.display->display, GC, GCForeground | GCFont, &v);
638 791
639 if (slow) 792 if (slow)
640 { 793 {
641 do 794 do
642 { 795 {
643 if (*xc) 796 if (*xc)
644 XDrawString (DISPLAY, DRAWABLE, GC, x, y + base, xc, 1); 797 XDrawString (d.display->display, d, GC, x, y + base, xc, 1);
645 798
646 x += r->TermWin.fwidth; 799 x += r->TermWin.fwidth;
647 xc++; len--; 800 xc++; len--;
648 } 801 }
649 while (len); 802 while (len);
650 } 803 }
651 else 804 else
652 XDrawString (DISPLAY, DRAWABLE, GC, x, y + base, xc, len); 805 XDrawString (d.display->display, d, GC, x, y + base, xc, len);
653 } 806 }
654 } 807 }
655} 808}
656 809
657///////////////////////////////////////////////////////////////////////////// 810/////////////////////////////////////////////////////////////////////////////
662//#define SWATHBITS (UNIBITS / 2 + 3) // minimum size for "full" tables 815//#define SWATHBITS (UNIBITS / 2 + 3) // minimum size for "full" tables
663#define SWATHBITS 8 816#define SWATHBITS 8
664#endif 817#endif
665 818
666struct rxvt_font_xft : rxvt_font { 819struct rxvt_font_xft : rxvt_font {
667 rxvt_font_xft () { f = 0; d = 0; } 820 rxvt_font_xft () { f = 0; }
668 821
669 void clear (); 822 void clear ();
670 823
671 rxvt_fontprop properties (); 824 rxvt_fontprop properties ();
672 825
673 bool load (const rxvt_fontprop &prop); 826 bool load (const rxvt_fontprop &prop);
674 827
675 void draw (int x, int y, 828 void draw (rxvt_drawable &d, int x, int y,
676 const text_t *text, int len, 829 const text_t *text, int len,
677 int fg, int bg); 830 int fg, int bg);
678 831
679 bool has_codepoint (uint32_t unicode); 832 bool has_codepoint (unicode_t unicode);
680 833
681protected: 834protected:
682 XftFont *f; 835 XftFont *f;
683 XftDraw *d;
684}; 836};
685 837
686void 838void
687rxvt_font_xft::clear () 839rxvt_font_xft::clear ()
688{ 840{
689 if (f) 841 if (f)
690 { 842 {
691 XftFontClose (DISPLAY, f); 843 XftFontClose (DISPLAY, f);
692 f = 0; 844 f = 0;
693 }
694
695 if (d)
696 {
697 XftDrawDestroy (d);
698 d = 0;
699 } 845 }
700} 846}
701 847
702rxvt_fontprop 848rxvt_fontprop
703rxvt_font_xft::properties () 849rxvt_font_xft::properties ()
736 FcPatternAddInteger (p, FC_WEIGHT, prop.weight); 882 FcPatternAddInteger (p, FC_WEIGHT, prop.weight);
737 883
738 if (FcPatternGet (p, FC_SLANT, 0, &v) != FcResultMatch) 884 if (FcPatternGet (p, FC_SLANT, 0, &v) != FcResultMatch)
739 FcPatternAddInteger (p, FC_SLANT, prop.slant); 885 FcPatternAddInteger (p, FC_SLANT, prop.slant);
740 886
887#if 0 // clipping unfortunately destroys our precious double-width-characters
741 // clip width, we can't do better, or can we? 888 // clip width, we can't do better, or can we?
742 if (FcPatternGet (p, FC_CHAR_WIDTH, 0, &v) != FcResultMatch) 889 if (FcPatternGet (p, FC_CHAR_WIDTH, 0, &v) != FcResultMatch)
743 FcPatternAddInteger (p, FC_CHAR_WIDTH, prop.width); 890 FcPatternAddInteger (p, FC_CHAR_WIDTH, prop.width);
891#endif
744 892
745 //FcPatternAddBool (p, FC_MINSPACE, 1); 893 //FcPatternAddBool (p, FC_MINSPACE, 1);
746 894
747 XftResult result; 895 XftResult result;
748 FcPattern *match = XftFontMatch (DISPLAY, DefaultScreen (DISPLAY), p, &result); 896 FcPattern *match = XftFontMatch (DISPLAY, DefaultScreen (DISPLAY), p, &result);
802 950
803 return true; 951 return true;
804} 952}
805 953
806bool 954bool
807rxvt_font_xft::has_codepoint (uint32_t unicode) 955rxvt_font_xft::has_codepoint (unicode_t unicode)
808{ 956{
809 return XftCharExists (DISPLAY, f, unicode); 957 return XftCharExists (DISPLAY, f, unicode);
810} 958}
811 959
812void 960void
813rxvt_font_xft::draw (int x, int y, 961rxvt_font_xft::draw (rxvt_drawable &d, int x, int y,
814 const text_t *text, int len, 962 const text_t *text, int len,
815 int fg, int bg) 963 int fg, int bg)
816{ 964{
817 if (!d)
818 {
819 dR;
820 d = XftDrawCreate (DISPLAY, DRAWABLE, XVISUAL, XCMAP);
821 }
822
823 if (bg >= 0 && bg != Color_bg)
824 XftDrawRect (d, &r->PixColors[bg].c, x, y, r->TermWin.fwidth * len, r->TermWin.fheight);
825 else
826 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);
827 966
828 if (!slow && width == r->TermWin.fwidth) 967 if (!slow && width == r->TermWin.fwidth && 0)
829 { 968 {
830 if (sizeof (text_t) == sizeof (FcChar16)) 969 if (sizeof (text_t) == sizeof (FcChar16))
831 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);
832 else 971 else
833 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);
836 { 975 {
837 while (len) 976 while (len)
838 { 977 {
839 if (*text != NOCHAR && *text != ' ') 978 if (*text != NOCHAR && *text != ' ')
840 { 979 {
980 int fwidth = r->TermWin.fwidth;
981 if (len >= 2 && text[1] == NOCHAR)
982 fwidth *= 2;
983
984 XGlyphInfo extents;
841 if (sizeof (text_t) == sizeof (FcChar16)) 985 if (sizeof (text_t) == sizeof (FcChar16))
842 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 }
843 else 991 else
844 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 }
845 } 998 }
846 999
847 x += r->TermWin.fwidth; 1000 x += r->TermWin.fwidth;
848 text++; 1001 text++;
849 len--; 1002 len--;
853#endif 1006#endif
854 1007
855///////////////////////////////////////////////////////////////////////////// 1008/////////////////////////////////////////////////////////////////////////////
856 1009
857rxvt_fontset::rxvt_fontset (rxvt_t r) 1010rxvt_fontset::rxvt_fontset (rxvt_t r)
858#ifdef EXPLICIT_CONTEXT
859: r(r) 1011: r (r)
860#endif
861{ 1012{
862 clear (); 1013 clear ();
863} 1014}
864 1015
865rxvt_fontset::~rxvt_fontset () 1016rxvt_fontset::~rxvt_fontset ()
868} 1019}
869 1020
870void 1021void
871rxvt_fontset::clear () 1022rxvt_fontset::clear ()
872{ 1023{
873 for (rxvt_font **i = fonts.begin (); i != fonts.end(); i++) 1024 for (rxvt_font **i = fonts.begin (); i != fonts.end (); i++)
874 FONT_UNREF (*i); 1025 FONT_UNREF (*i);
875 1026
876 fonts.clear (); 1027 fonts.clear ();
877 base_id = 0; 1028 base_id = 0;
878 base_prop.height = 0x7fffffff; 1029 base_prop.height = 0x7fffffff;
905 f = new rxvt_font_x11; 1056 f = new rxvt_font_x11;
906 } 1057 }
907 else 1058 else
908 f = new rxvt_font_x11; 1059 f = new rxvt_font_x11;
909 1060
1061 f->fs = this;
910 f->set_term (r); 1062 f->set_term (r);
911 f->set_name (strdup (name)); 1063 f->set_name (strdup (name));
912 1064
913 f->cs = cs; 1065 f->cs = cs;
914 f->loaded = false; 1066 f->loaded = false;
932 1084
933 if (*desc == '[') 1085 if (*desc == '[')
934 { 1086 {
935 fprintf (stderr, "extra font parameters not yet supported, skipping.\n"); 1087 fprintf (stderr, "extra font parameters not yet supported, skipping.\n");
936 1088
937 const char *extra = desc++; 1089 //const char *extra = desc++; // not yet used
938 1090
939 desc = strchr (desc, ']'); 1091 desc = strchr (desc, ']');
940 1092
941 if (!desc) 1093 if (!desc)
942 { 1094 {
981 } 1133 }
982 1134
983 return true; 1135 return true;
984} 1136}
985 1137
986void 1138bool
987rxvt_fontset::populate (const char *desc) 1139rxvt_fontset::populate (const char *desc)
988{ 1140{
989 clear (); 1141 clear ();
990 1142
991 fonts.push_back (new_font (0, CS_UNICODE)); 1143 fonts.push_back (new_font (0, CS_UNICODE));
995 1147
996 if (!base_id) 1148 if (!base_id)
997 base_id = 1; 1149 base_id = 1;
998 1150
999 // we currently need a base-font, no matter what 1151 // we currently need a base-font, no matter what
1000 if (fonts.size () <= base_id || !realize_font (base_id)) 1152 if ((int)fonts.size () <= base_id || !realize_font (base_id))
1001 { 1153 {
1154 puts ("unable to load specified font (s), falling back to 'fixed'\n");
1002 add_fonts ("fixed"); 1155 add_fonts ("fixed");
1003 base_id = fonts.size () - 1; 1156 base_id = fonts.size () - 1;
1004 } 1157 }
1005 1158
1006 if (fonts.size () <= base_id || !realize_font (base_id)) 1159 if ((int)fonts.size () <= base_id || !realize_font (base_id))
1007 { 1160 return false;
1008 fprintf (stderr, "unable to load a base font, please provide one using -fn fontname\n");
1009 exit (1);
1010 }
1011 1161
1012 base_prop = fonts[base_id]->properties (); 1162 base_prop = fonts[base_id]->properties ();
1163
1164 return true;
1013} 1165}
1014 1166
1015int 1167int
1016rxvt_fontset::find_font (uint32_t unicode) 1168rxvt_fontset::find_font (unicode_t unicode)
1017{ 1169{
1018 for (int i = 0; i < fonts.size (); i++) 1170 for (unsigned int i = 0; i < fonts.size (); i++)
1019 { 1171 {
1020 rxvt_font *f = fonts[i]; 1172 rxvt_font *f = fonts[i];
1021 1173
1022 if (!f->loaded) 1174 if (!f->loaded)
1023 { 1175 {

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines