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.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
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 TGC 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;
33} fallback_fonts[] = { 34} fallback_fonts[] = {
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, TGC, r->PixColors[color]);
169 XFillRectangle (DISPLAY, DRAWABLE, GC, x, y, w, h); 200 XFillRectangle (d.display->display, d, TGC, x, y, w, h);
201#endif
170 } 202 }
171} 203}
172 204
173static const char *linedraw_cmds[128] = { 205static const char *linedraw_cmds[128 + 32] = {
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",
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",
220 264
221 // to be done 265 // to be done
222}; 266};
223 267
224struct rxvt_font_default : rxvt_font { 268struct rxvt_font_default : rxvt_font {
225 bool load (int maxheight) 269 rxvt_fontprop properties ()
270 {
271 rxvt_fontprop p;
272
273 p.width = p.height = 1;
274 p.weight = rxvt_fontprop::medium;
275 p.slant = rxvt_fontprop::roman;
276
277 return p;
278 }
279
280 bool load (const rxvt_fontprop &prop)
226 { 281 {
227 width = 1; height = 1; 282 width = 1; height = 1;
228 ascent = 1; descent = 0; 283 ascent = 1; descent = 0;
229 284
285 set_name ("built-in pseudofont");
286
230 return true; 287 return true;
231 } 288 }
232 289
233 bool has_codepoint (uint32_t unicode) 290 bool has_codepoint (unicode_t unicode)
234 { 291 {
235 if (unicode <= 0x001f) 292 if (unicode <= 0x001f)
236 return true; 293 return true;
294
237 if (unicode >= 0x0080 && unicode <= 0x009f) 295 if (unicode >= 0x0080 && unicode <= 0x009f)
238 return true; 296 return true;
239 297
240 if (unicode >= 0x2500 && unicode <= 0x257f 298 if (unicode >= 0x2500 && unicode <= 0x257f
241 && 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))
242 return true; 306 return true;
243 307
244 switch (unicode) 308 switch (unicode)
245 { 309 {
246 case ZERO_WIDTH_CHAR: 310 case ZERO_WIDTH_CHAR:
248 } 312 }
249 313
250 return false; 314 return false;
251 } 315 }
252 316
253 void draw (int x, int y, 317 void draw (rxvt_drawable &d, int x, int y,
254 const text_t *text, int len, 318 const text_t *text, int len,
255 int fg, int bg); 319 int fg, int bg);
256}; 320};
257 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
258void 344void
259rxvt_font_default::draw (int x, int y, 345rxvt_font_default::draw (rxvt_drawable &d, int x, int y,
260 const text_t *text, int len, 346 const text_t *text, int len,
261 int fg, int bg) 347 int fg, int bg)
262{ 348{
263 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);
264 350
265 XSetForeground (DISPLAY, GC, r->PixColors[fg]); 351 XSetForeground (d.display->display, TGC, r->PixColors[fg]);
266 352
267 while (len--) 353 while (len--)
268 { 354 {
355#if ENABLE_COMBINING
356 compose_char *cc;
357#endif
269 text_t t = *text++; 358 text_t t = *text++;
270 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?
271 if (t >= 0x2500 & t <= 0x2580 && linedraw_cmds[t - 0x2500]) 366 if (t >= 0x2500 & t <= 0x259f && linedraw_cmds[t - 0x2500])
272 { 367 {
273 const char *p = linedraw_cmds[t - 0x2500]; 368 const char *p = linedraw_cmds[t - 0x2500];
274 369
275 int x0 = x, x1 = x + r->TermWin.fwidth / 2, x2 = x + r->TermWin.fwidth ;
276 int y0 = y, y1 = y + r->TermWin.fheight / 2, y2 = y + r->TermWin.fheight;
277
278 XGCValues gcv; 370 XGCValues gcv;
371
372 gcv.cap_style = CapNotLast;
373 XChangeGC (d.display->display, TGC, GCCapStyle, &gcv);
279 374
280 while (*p) 375 while (*p)
281 { 376 {
282 switch (*p++) 377 switch (*p++)
283 { 378 {
284 case '1': 379 case '1':
285 gcv.line_width = 0; 380 gcv.line_width = 0;
286 XChangeGC (DISPLAY, GC, GCLineWidth, &gcv); 381 XChangeGC (d.display->display, TGC, GCLineWidth, &gcv);
287 break; 382 break;
288 383
289 case '2': 384 case '2':
290 gcv.line_width = 2; 385 gcv.line_width = 3;
291 XChangeGC (DISPLAY, GC, GCLineWidth, &gcv); 386 XChangeGC (d.display->display, TGC, GCLineWidth, &gcv);
292 break; 387 break;
293 388
294 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;
295 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;
296 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;
297 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
298 case 'a': XDrawLine (DISPLAY, DRAWABLE, GC, x0, y2, x2, y0); break; 396 case '/' : XDrawLine (d.display->display, d, TGC, x0, y2, x2 , y0 ); break;
299 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;
300 } 408 }
301 } 409 }
302 410
303 gcv.line_width = 0; 411 gcv.line_width = 0;
304 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]))
305 } 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
306 else 431 else
307 switch (*text++) 432 switch (t)
308 { 433 {
309 case NOCHAR:
310 case ZERO_WIDTH_CHAR: 434 case ZERO_WIDTH_CHAR:
311 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
312 default: 462 default:
313 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;
314 } 474 }
315 475
316 x += r->TermWin.fwidth; 476 x += r->TermWin.fwidth;
317 } 477 }
318} 478}
322struct rxvt_font_x11 : rxvt_font { 482struct rxvt_font_x11 : rxvt_font {
323 rxvt_font_x11 () { f = 0; } 483 rxvt_font_x11 () { f = 0; }
324 484
325 void clear (); 485 void clear ();
326 486
327 bool load (int maxheight); 487 rxvt_fontprop properties ();
328 488
489 bool load (const rxvt_fontprop &prop);
490
329 bool has_codepoint (uint32_t unicode); 491 bool has_codepoint (unicode_t unicode);
330 492
331 void draw (int x, int y, 493 void draw (rxvt_drawable &d, int x, int y,
332 const text_t *text, int len, 494 const text_t *text, int len,
333 int fg, int bg); 495 int fg, int bg);
334 496
335 XFontStruct *f; 497 XFontStruct *f;
336 codeset cs; 498 codeset cs;
337 bool enc2b, encm; 499 bool enc2b, encm;
338 500
339 const char *get_property (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);
340}; 505};
341 506
342const char * 507const char *
343rxvt_font_x11::get_property (const char *property, const char *repl) const 508rxvt_font_x11::get_property (XFontStruct *f, const char *property, const char *repl) const
344{ 509{
345 unsigned long value; 510 unsigned long value;
346 511
347 if (XGetFontProperty (f, XInternAtom (DISPLAY, property, 0), &value)) 512 if (XGetFontProperty (f, XInternAtom (DISPLAY, property, 0), &value))
348 return XGetAtomName (DISPLAY, value); 513 return XGetAtomName (DISPLAY, value);
349 else 514 else
350 return repl; 515 return repl;
351} 516}
352 517
518rxvt_fontprop
519rxvt_font_x11::properties ()
520{
521 rxvt_fontprop p;
522 set_properties (p, f);
523 return p;
524}
525
353bool 526bool
354rxvt_font_x11::load (int maxheight) 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{
540 const char *weight = get_property (f, "WEIGHT_NAME", "medium");
541 const char *slant = get_property (f, "SLANT", "r");
542
543 unsigned long height;
544 if (!XGetFontProperty (f, XInternAtom (DISPLAY, "PIXEL_SIZE", 0), &height))
545 return false;
546
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);
615}
616
617bool
618rxvt_font_x11::load (const rxvt_fontprop &prop)
355{ 619{
356 clear (); 620 clear ();
621
622 char **list;
623 int count;
624 list = XListFonts (DISPLAY, name, 512, &count);
625 set_name (0);
626
627 if (!list)
628 return false;
629
630 int bestdiff = 0x7fffffff;
631 for (int i = 0; i < count; i++)
632 {
633 rxvt_fontprop p;
634 char fname[1024];
635 fix_scalable (fname, list[i], prop);
636
637 if (!set_properties (p, fname))
638 continue;
639
640 if (p.height > prop.height) // weed out too large fonts
641 continue;
642
643 int diff = (prop.height - p.height) * 32
644 + abs (prop.weight - p.weight)
645 + abs (prop.slant - p.slant );
646
647 if (!name // compare against best found so far
648 || diff < bestdiff)
649 {
650 set_name (strdup (fname));
651 bestdiff = diff;
652 }
653 }
654
655 XFreeFontNames (list);
656
657 if (!name)
658 return false;
357 659
358 f = XLoadQueryFont (DISPLAY, name); 660 f = XLoadQueryFont (DISPLAY, name);
359 661
360 if (!f) 662 if (!f)
361 return false; 663 return false;
362 664
363 unsigned long value;
364
365 const char *registry = get_property ("CHARSET_REGISTRY", 0); 665 const char *registry = get_property (f, "CHARSET_REGISTRY", 0);
366 const char *encoding = get_property ("CHARSET_ENCODING", 0); 666 const char *encoding = get_property (f, "CHARSET_ENCODING", 0);
367 667
368 if (registry && encoding) 668 if (registry && encoding)
369 { 669 {
370 char charset[64]; 670 char charset[64];
371 snprintf (charset, 64, "%s-%s", registry, encoding); 671 snprintf (charset, 64, "%s-%s", registry, encoding);
372 672
373 cs = codeset_from_name (charset); 673 cs = codeset_from_name (charset);
374 } 674 }
375 else 675 else
376 { 676 {
377 const char *charset = get_property ("FONT", 0); 677 const char *charset = get_property (f, "FONT", 0);
378 678
379 if (!charset) 679 if (!charset)
380 charset = name; 680 charset = name;
381 681
382 int count = 13; 682 int count = 13;
395 695
396 ascent = f->ascent; 696 ascent = f->ascent;
397 descent = f->descent; 697 descent = f->descent;
398 height = ascent + descent; 698 height = ascent + descent;
399 699
400 prop = false; 700 slow = false;
401 701
402 if (f->min_bounds.width == f->max_bounds.width) 702 if (f->min_bounds.width == f->max_bounds.width)
403 width = f->min_bounds.width; 703 width = f->min_bounds.width;
404 else if (f->per_char == NULL) 704 else if (f->per_char == NULL)
405 width = f->max_bounds.width; 705 width = f->max_bounds.width;
406 else 706 else
407 { 707 {
408 prop = true; 708 slow = true;
409 709
410 int N = f->max_char_or_byte2 - f->min_char_or_byte2; 710 int N = f->max_char_or_byte2 - f->min_char_or_byte2;
411 711
412 if (encm) 712 if (encm)
413 N += (f->max_byte1 - f->min_byte1) 713 N += (f->max_byte1 - f->min_byte1)
443 f = 0; 743 f = 0;
444 } 744 }
445} 745}
446 746
447bool 747bool
448rxvt_font_x11::has_codepoint (uint32_t unicode) 748rxvt_font_x11::has_codepoint (unicode_t unicode)
449{ 749{
450 uint32_t ch = FROM_UNICODE (cs, unicode); 750 uint32_t ch = FROM_UNICODE (cs, unicode);
451 751
452 if (ch == NOCHAR) 752 if (ch == NOCHAR)
453 return false; 753 return false;
455 /* check wether the character exists in _this_ font. horrible. */ 755 /* check wether the character exists in _this_ font. horrible. */
456 XCharStruct *xcs; 756 XCharStruct *xcs;
457 757
458 if (encm) 758 if (encm)
459 { 759 {
460 int byte1 = ch >> 8; 760 unsigned char byte1 = ch >> 8;
461 int byte2 = ch & 255; 761 unsigned char byte2 = ch & 255;
462 762
463 if (byte1 < f->min_byte1 || byte1 > f->max_byte1 763 if (byte1 < f->min_byte1 || byte1 > f->max_byte1
464 || 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)
465 return false; 765 return false;
466 766
489 789
490 return true; 790 return true;
491} 791}
492 792
493void 793void
494rxvt_font_x11::draw (int x, int y, 794rxvt_font_x11::draw (rxvt_drawable &d, int x, int y,
495 const text_t *text, int len, 795 const text_t *text, int len,
496 int fg, int bg) 796 int fg, int bg)
497{ 797{
498 // this looks like a mess /. 798 // this looks like a mess /.
499 // and it is a mess /. 799 // and it is a mess /.
500 // yet we are trying to be perfect /. 800 // yet we are trying to be perfect /.
501 // but the result still isn't perfect /. 801 // but the result still isn't perfect /.
502 802
503 bool slow = prop 803 bool slow = this->slow
504 || width != r->TermWin.fwidth 804 || width != r->TermWin.fwidth
505 || height != r->TermWin.fheight; 805 || height != r->TermWin.fheight;
506 806
507 int base = r->TermWin.fbase; 807 int base = r->TermWin.fbase;
508 808
515 { 815 {
516 const XChar2b *xc = enc_xchar2b (text, len, cs, slow); 816 const XChar2b *xc = enc_xchar2b (text, len, cs, slow);
517 817
518 if (bg == Color_bg && !slow) 818 if (bg == Color_bg && !slow)
519 { 819 {
520 XChangeGC (DISPLAY, GC, GCForeground | GCBackground | GCFont, &v); 820 XChangeGC (d.display->display, TGC, GCForeground | GCBackground | GCFont, &v);
521 XDrawImageString16 (DISPLAY, DRAWABLE, GC, x, y + base, xc, len); 821 XDrawImageString16 (d.display->display, d, TGC, x, y + base, xc, len);
522 } 822 }
523 else 823 else
524 { 824 {
525 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);
526 826
527 XChangeGC (DISPLAY, GC, GCForeground | GCFont, &v); 827 XChangeGC (d.display->display, TGC, GCForeground | GCFont, &v);
528 828
529 if (slow) 829 if (slow)
530 { 830 {
531 do 831 do
532 { 832 {
533 if (xc->byte1 || xc->byte2) 833 if (xc->byte1 || xc->byte2)
534 XDrawString16 (DISPLAY, DRAWABLE, GC, x, y + base, xc, 1); 834 XDrawString16 (d.display->display, d, TGC, x, y + base, xc, 1);
535 835
536 x += r->TermWin.fwidth; 836 x += r->TermWin.fwidth;
537 xc++; len--; 837 xc++; len--;
538 } 838 }
539 while (len); 839 while (len);
540 } 840 }
541 else 841 else
542 XDrawString16 (DISPLAY, DRAWABLE, GC, x, y + base, xc, len); 842 XDrawString16 (d.display->display, d, TGC, x, y + base, xc, len);
543 } 843 }
544 } 844 }
545 else 845 else
546 { 846 {
547 const char *xc = enc_char (text, len, cs, slow); 847 const char *xc = enc_char (text, len, cs, slow);
548 848
549 if (bg == Color_bg && !slow) 849 if (bg == Color_bg && !slow)
550 { 850 {
551 XChangeGC (DISPLAY, GC, GCForeground | GCBackground | GCFont, &v); 851 XChangeGC (d.display->display, TGC, GCForeground | GCBackground | GCFont, &v);
552 XDrawImageString (DISPLAY, DRAWABLE, GC, x, y + base, xc, len); 852 XDrawImageString (d.display->display, d, TGC, x, y + base, xc, len);
553 } 853 }
554 else 854 else
555 { 855 {
556 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);
557 857
558 XChangeGC (DISPLAY, GC, GCForeground | GCFont, &v); 858 XChangeGC (d.display->display, TGC, GCForeground | GCFont, &v);
559 859
560 if (slow) 860 if (slow)
561 { 861 {
562 do 862 do
563 { 863 {
564 if (*xc) 864 if (*xc)
565 XDrawString (DISPLAY, DRAWABLE, GC, x, y + base, xc, 1); 865 XDrawString (d.display->display, d, TGC, x, y + base, xc, 1);
566 866
567 x += r->TermWin.fwidth; 867 x += r->TermWin.fwidth;
568 xc++; len--; 868 xc++; len--;
569 } 869 }
570 while (len); 870 while (len);
571 } 871 }
572 else 872 else
573 XDrawString (DISPLAY, DRAWABLE, GC, x, y + base, xc, len); 873 XDrawString (d.display->display, d, TGC, x, y + base, xc, len);
574 } 874 }
575 } 875 }
576} 876}
577 877
578///////////////////////////////////////////////////////////////////////////// 878/////////////////////////////////////////////////////////////////////////////
583//#define SWATHBITS (UNIBITS / 2 + 3) // minimum size for "full" tables 883//#define SWATHBITS (UNIBITS / 2 + 3) // minimum size for "full" tables
584#define SWATHBITS 8 884#define SWATHBITS 8
585#endif 885#endif
586 886
587struct rxvt_font_xft : rxvt_font { 887struct 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; } 888 rxvt_font_xft () { f = 0; }
615 889
616 void clear (); 890 void clear ();
617 891
618 bool load (int maxheight); 892 rxvt_fontprop properties ();
619 893
620 void draw (int x, int y, 894 bool load (const rxvt_fontprop &prop);
895
896 void draw (rxvt_drawable &d, int x, int y,
621 const text_t *text, int len, 897 const text_t *text, int len,
622 int fg, int bg); 898 int fg, int bg);
623 899
624 bool has_codepoint (uint32_t unicode); 900 bool has_codepoint (unicode_t unicode);
625 901
626protected: 902protected:
627 XftFont *f; 903 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}; 904};
638 905
639void 906void
640rxvt_font_xft::clear () 907rxvt_font_xft::clear ()
641{ 908{
642 if (f) 909 if (f)
643 { 910 {
644 XftFontClose (DISPLAY, f); 911 XftFontClose (DISPLAY, f);
645 f = 0; 912 f = 0;
646 } 913 }
914}
647 915
648 if (d) 916rxvt_fontprop
649 { 917rxvt_font_xft::properties ()
650 XftDrawDestroy (d); 918{
651 d = 0; 919 rxvt_fontprop p;
652 }
653 920
654#if 0 921 FT_Face face = XftLockFace (f);
655 for (int i = 0; i < SWATHCOUNT; i++) 922
656 delete cvr[i]; 923 p.width = width; p.height = height;
657#endif 924 p.weight = face->style_flags & FT_STYLE_FLAG_BOLD ? rxvt_fontprop::bold : rxvt_fontprop::medium;
925 p.slant = face->style_flags & FT_STYLE_FLAG_ITALIC ? rxvt_fontprop::italic : rxvt_fontprop::roman;
926
927 XftUnlockFace (f);
928
929 return p;
658} 930}
659 931
660bool 932bool
661rxvt_font_xft::load (int maxheight) 933rxvt_font_xft::load (const rxvt_fontprop &prop)
662{ 934{
663#if 0 935#if 0
664 for (int i = 0; i < SWATHCOUNT; i++) 936 for (int i = 0; i < SWATHCOUNT; i++)
665 cvr[i] = 0; 937 cvr[i] = 0;
666#endif 938#endif
667 939
668 clear (); 940 clear ();
669 941
670 f = XftFontOpenName (DISPLAY, DefaultScreen (DISPLAY), name); 942 FcPattern *p = FcNameParse ((FcChar8 *) name);
943
944 if (!p)
945 return false;
946
947 FcValue v;
948
949 if (FcPatternGet (p, FC_WEIGHT, 0, &v) != FcResultMatch)
950 FcPatternAddInteger (p, FC_WEIGHT, prop.weight);
951
952 if (FcPatternGet (p, FC_SLANT, 0, &v) != FcResultMatch)
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
960
961 //FcPatternAddBool (p, FC_MINSPACE, 1);
962
963 XftResult result;
964 FcPattern *match = XftFontMatch (DISPLAY, DefaultScreen (DISPLAY), p, &result);
965
966 FcPatternDestroy (p);
967
968 if (!match)
969 return false;
970
971 f = XftFontOpenPattern (DISPLAY, match);
671 972
672 if (!f) 973 if (!f)
974 {
975 FcPatternDestroy (match);
673 return false; 976 return false;
977 }
674 978
675 FT_Face face = XftLockFace (f); 979 FT_Face face = XftLockFace (f);
676 980
677 prop = !FT_IS_FIXED_WIDTH (face); 981 slow = !FT_IS_FIXED_WIDTH (face);
678 982
679 int ftheight = 0; 983 int ftheight = 0;
680 984
681 for (;;) 985 for (;;)
682 { 986 {
684 FcChar8 c; 988 FcChar8 c;
685 989
686 c = 'i'; XftTextExtents8 (DISPLAY, f, &c, 1, &g1); 990 c = 'i'; XftTextExtents8 (DISPLAY, f, &c, 1, &g1);
687 c = 'W'; XftTextExtents8 (DISPLAY, f, &c, 1, &g2); 991 c = 'W'; XftTextExtents8 (DISPLAY, f, &c, 1, &g2);
688 992
689 prop = prop || g1.xOff != g2.xOff; // don't simply trust the font 993 if (g1.xOff != g2.xOff) // don't simply trust the font
994 slow = true;
690 995
691 width = g2.xOff; 996 width = g2.xOff;
692 ascent = (face->size->metrics.ascender + 63) >> 6; 997 ascent = (face->size->metrics.ascender + 63) >> 6;
693 descent = (-face->size->metrics.descender + 63) >> 6; 998 descent = (-face->size->metrics.descender + 63) >> 6;
694 height = ascent + descent; 999 height = ascent + descent;
695 1000
696 if (height <= maxheight || !maxheight) 1001 if (height <= prop.height || !prop.height)
697 break; 1002 break;
698 1003
699 if (ftheight) 1004 if (ftheight)
700 { 1005 {
701 // take smaller steps near the end 1006 // take smaller steps near the end
702 if (height > maxheight + 1) ftheight++; 1007 if (height > prop.height + 1) ftheight++;
703 if (height > maxheight + 2) ftheight++; 1008 if (height > prop.height + 2) ftheight++;
704 if (height > maxheight + 3) ftheight++; 1009 if (height > prop.height + 3) ftheight++;
705 1010
706 FT_Set_Pixel_Sizes (face, 0, ftheight -= height - maxheight); 1011 FT_Set_Pixel_Sizes (face, 0, ftheight -= height - prop.height);
707 } 1012 }
708 else 1013 else
709 FT_Set_Pixel_Sizes (face, 0, ftheight = maxheight); 1014 FT_Set_Pixel_Sizes (face, 0, ftheight = prop.height);
710 } 1015 }
711 1016
712 XftUnlockFace (f); 1017 XftUnlockFace (f);
713 1018
714 return true; 1019 return true;
715} 1020}
716 1021
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 1022bool
730rxvt_font_xft::has_codepoint (uint32_t unicode) 1023rxvt_font_xft::has_codepoint (unicode_t unicode)
731{ 1024{
732 return XftCharExists (DISPLAY, f, unicode); 1025 return XftCharExists (DISPLAY, f, unicode);
733} 1026}
734 1027
735void 1028void
736rxvt_font_xft::draw (int x, int y, 1029rxvt_font_xft::draw (rxvt_drawable &d, int x, int y,
737 const text_t *text, int len, 1030 const text_t *text, int len,
738 int fg, int bg) 1031 int fg, int bg)
739{ 1032{
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); 1033 clear_rect (d, x, y, r->TermWin.fwidth * len, r->TermWin.fheight, bg);
750 1034
751 if (!prop && width == r->TermWin.fwidth) 1035 if (!slow && width == r->TermWin.fwidth && 0)
752 { 1036 {
753 if (sizeof (text_t) == sizeof (FcChar16)) 1037 if (sizeof (text_t) == sizeof (FcChar16))
754 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);
755 else 1039 else
756 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);
759 { 1043 {
760 while (len) 1044 while (len)
761 { 1045 {
762 if (*text != NOCHAR && *text != ' ') 1046 if (*text != NOCHAR && *text != ' ')
763 { 1047 {
1048 int fwidth = r->TermWin.fwidth;
1049 if (len >= 2 && text[1] == NOCHAR)
1050 fwidth *= 2;
1051
1052 XGlyphInfo extents;
764 if (sizeof (text_t) == sizeof (FcChar16)) 1053 if (sizeof (text_t) == sizeof (FcChar16))
765 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 }
766 else 1059 else
767 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 }
768 } 1066 }
769 1067
770 x += r->TermWin.fwidth; 1068 x += r->TermWin.fwidth;
771 text++; 1069 text++;
772 len--; 1070 len--;
776#endif 1074#endif
777 1075
778///////////////////////////////////////////////////////////////////////////// 1076/////////////////////////////////////////////////////////////////////////////
779 1077
780rxvt_fontset::rxvt_fontset (rxvt_t r) 1078rxvt_fontset::rxvt_fontset (rxvt_t r)
781#ifdef EXPLICIT_CONTEXT
782: r(r) 1079: r (r)
783#endif
784{ 1080{
785 clear (); 1081 clear ();
786} 1082}
787 1083
788rxvt_fontset::~rxvt_fontset () 1084rxvt_fontset::~rxvt_fontset ()
791} 1087}
792 1088
793void 1089void
794rxvt_fontset::clear () 1090rxvt_fontset::clear ()
795{ 1091{
796 for (rxvt_font **i = fonts.begin (); i != fonts.end(); i++) 1092 for (rxvt_font **i = fonts.begin (); i != fonts.end (); i++)
797 FONT_UNREF (*i); 1093 FONT_UNREF (*i);
798 1094
799 fonts.clear (); 1095 fonts.clear ();
800 base_id = 0; 1096 base_id = 0;
801 height = 0x7fffffff; 1097 base_prop.height = 0x7fffffff;
1098 base_prop.weight = rxvt_fontprop::medium;
1099 base_prop.slant = rxvt_fontprop::roman;
802 1100
803 fallback = fallback_fonts; 1101 fallback = fallback_fonts;
804} 1102}
805 1103
806rxvt_font * 1104rxvt_font *
826 f = new rxvt_font_x11; 1124 f = new rxvt_font_x11;
827 } 1125 }
828 else 1126 else
829 f = new rxvt_font_x11; 1127 f = new rxvt_font_x11;
830 1128
1129 f->fs = this;
831 f->set_term (r); 1130 f->set_term (r);
832 f->set_name (strdup (name)); 1131 f->set_name (strdup (name));
833 1132
834 f->cs = cs; 1133 f->cs = cs;
835 f->loaded = false; 1134 f->loaded = false;
853 1152
854 if (*desc == '[') 1153 if (*desc == '[')
855 { 1154 {
856 fprintf (stderr, "extra font parameters not yet supported, skipping.\n"); 1155 fprintf (stderr, "extra font parameters not yet supported, skipping.\n");
857 1156
858 const char *extra = desc++; 1157 //const char *extra = desc++; // not yet used
859 1158
860 desc = strchr (desc, ']'); 1159 desc = strchr (desc, ']');
861 1160
862 if (!desc) 1161 if (!desc)
863 { 1162 {
891rxvt_fontset::realize_font (int i) 1190rxvt_fontset::realize_font (int i)
892{ 1191{
893 if (fonts[i]->loaded) 1192 if (fonts[i]->loaded)
894 return true; 1193 return true;
895 1194
896 if (fonts[i]->load (height))
897 return fonts[i]->loaded = true; 1195 fonts[i]->loaded = true;
898 1196
899 delete fonts[i]; 1197 if (!fonts[i]->load (base_prop))
900 fonts.erase (fonts.begin () + i); 1198 {
901 1199 fonts[i]->cs = CS_UNKNOWN;
902 return false; 1200 return false;
903} 1201 }
904 1202
905void 1203 return true;
1204}
1205
1206bool
906rxvt_fontset::populate (const char *desc) 1207rxvt_fontset::populate (const char *desc)
907{ 1208{
908 clear (); 1209 clear ();
909 1210
910 fonts.push_back (new_font (0, CS_UNICODE)); 1211 fonts.push_back (new_font (0, CS_UNICODE));
914 1215
915 if (!base_id) 1216 if (!base_id)
916 base_id = 1; 1217 base_id = 1;
917 1218
918 // we currently need a base-font, no matter what 1219 // we currently need a base-font, no matter what
919 if (fonts.size () <= base_id) 1220 if ((int)fonts.size () <= base_id || !realize_font (base_id))
920 { 1221 {
1222 puts ("unable to load specified font (s), falling back to 'fixed'\n");
921 add_fonts ("fixed"); 1223 add_fonts ("fixed");
922 base_id = 1; 1224 base_id = fonts.size () - 1;
923 } 1225 }
924 1226
925 if (fonts.size () <= base_id || !realize_font (base_id)) 1227 if ((int)fonts.size () <= base_id || !realize_font (base_id))
926 { 1228 return false;
927 fprintf (stderr, "unable to load a base font, please provide one using -fn fontname\n");
928 exit (1);
929 }
930 1229
931 height = fonts[base_id]->height; 1230 base_prop = fonts[base_id]->properties ();
932 1231
933 /*add_fonts ("-efont-fixed-medium-r-normal-*-14-*-*-*-*-*-iso10646-1,"*/ 1232 return true;
934} 1233}
935 1234
936int 1235int
937rxvt_fontset::find_font (uint32_t unicode) 1236rxvt_fontset::find_font (unicode_t unicode)
938{ 1237{
939 for (int i = 0; i < fonts.size (); i++) 1238 for (unsigned int i = 0; i < fonts.size (); i++)
940 { 1239 {
941 rxvt_font *f = fonts[i]; 1240 rxvt_font *f = fonts[i];
942 1241
943 if (!f->loaded) 1242 if (!f->loaded)
944 { 1243 {
945 if (FROM_UNICODE (f->cs, unicode) == NOCHAR) 1244 if (FROM_UNICODE (f->cs, unicode) == NOCHAR)
946 goto next_font; 1245 goto next_font;
947 1246
948 if (!realize_font (i)) 1247 if (!realize_font (i))
949 {
950 --i;
951 goto next_font; 1248 goto next_font;
952 } 1249 }
953 1250
954 //printf ("added font %s for %04lx\n", f->name, unicode);
955 }
956
957 if (f->has_codepoint (unicode)) 1251 if (f->cs != CS_UNKNOWN && f->has_codepoint (unicode))
958 return i; 1252 return i;
959 1253
960 next_font: 1254 next_font:
961 if (i == fonts.size () - 1 && fallback->name) 1255 if (i == fonts.size () - 1 && fallback->name)
962 { 1256 {
963 fonts.push_back (new_font (fallback->name, fallback->cs)); 1257 fonts.push_back (new_font (fallback->name, fallback->cs));
964 fallback++; 1258 fallback++;
1259 i = 0;
965 } 1260 }
966 } 1261 }
967 1262
968 return 0; /* we must return SOME font */ 1263 return 0; /* we must return SOME font */
969} 1264}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines