~kklimonda/ubuntu/lucid/rxvt-unicode/lp-514821

« back to all changes in this revision

Viewing changes to src/rxvtfont.C

  • Committer: Bazaar Package Importer
  • Author(s): Decklin Foster
  • Date: 2006-09-01 14:44:58 UTC
  • mfrom: (1.2.1 upstream) (9 edgy)
  • mto: (3.2.1 squeeze)
  • mto: This revision was merged to the branch mainline in revision 10.
  • Revision ID: james.westby@ubuntu.com-20060901144458-3jn5sjka9gpg0v9i
* Edit the comments in the app-defaults file, and disable all settings by
  default. If font autoselection fails, I would prefer to open a new bug
  specifically for that. (Closes: #385481)
* Reorganize and edit README.Debian, pushing as much as possible into FAQ
  format (with resource setting issues first).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*--------------------------------*-C-*---------------------------------*
 
1
/*----------------------------------------------------------------------*
2
2
 * File:        rxvtfont.C
3
3
 *----------------------------------------------------------------------*
4
 
 * Copyright (c) 2003-2004 Marc Lehmann <pcg@goof.com>
 
4
 * Copyright (c) 2003-2006 Marc Lehmann <pcg@goof.com>
5
5
 *                              - original version.
6
6
 *
7
7
 * This program is free software; you can redistribute it and/or modify
16
16
 *
17
17
 * You should have received a copy of the GNU General Public License
18
18
 * along with this program; if not, write to the Free Software
19
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
20
 *---------------------------------------------------------------------*/
21
21
 
22
22
#include "../config.h"
23
23
#include "rxvt.h"
 
24
#include "rxvtlib.h"
24
25
#include "rxvtutil.h"
25
26
#include "rxvtfont.h"
26
27
 
27
28
#include <cstdlib>
28
 
#include <wchar.h>
 
29
 
29
30
#include <inttypes.h>
30
31
 
31
 
#define DISPLAY  r->display->display
32
 
#define TGC      r->TermWin.gc
 
32
#define MAX_OVERLAP_ROMAN  (8 + 2)      // max. character width in 8ths of the base width
 
33
#define MAX_OVERLAP_ITALIC (8 + 3)      // max. overlap for italic fonts
33
34
 
34
 
#define MAX_OVERLAP (4 + 1)     // max. character width in 4ths of the base width
 
35
#define OVERLAP_OK(w,wcw,prop) ((w) <= (                        \
 
36
  (prop)->slant >= rxvt_fontprop::italic                        \
 
37
    ? ((prop)->width * (wcw) * MAX_OVERLAP_ITALIC + 7) >> 3     \
 
38
    : ((prop)->width * (wcw) * MAX_OVERLAP_ROMAN  + 7) >> 3     \
 
39
  ))
35
40
 
36
41
const struct rxvt_fallback_font {
37
42
  codeset cs;
61
66
  { CS_ISO8859_16,   "-*-*-*-r-*--*-*-*-*-c-*-iso8859-16"          },
62
67
 
63
68
# if XFT
64
 
  { CS_KOI8_U,       "xft::spacing=100:lang=ru:antialias=false"    },
65
 
 
66
 
  { CS_ISO8859_5,    "xft::spacing=100:lang=ru:antialias=false"    },
67
 
  { CS_ISO8859_6,    "xft::spacing=100:lang=ar:antialias=false"    },
68
 
  { CS_ISO8859_7,    "xft::spacing=100:lang=el:antialias=false"    },
69
 
  { CS_ISO8859_8,    "xft::spacing=100:lang=he:antialias=false"    },
70
 
  { CS_ISO8859_9,    "xft::spacing=100:lang=tr:antialias=false"    },
71
 
  { CS_ISO8859_10,   "xft::spacing=100:lang=se:antialias=false"    },
72
 
  { CS_ISO8859_11,   "xft::spacing=100:lang=th:antialias=false"    },
 
69
  { CS_KOI8_U,       "xft::lang=ru"                                },
 
70
                                                                   
 
71
  { CS_ISO8859_5,    "xft::lang=ru"                                },
 
72
  { CS_ISO8859_6,    "xft::lang=ar"                                },
 
73
  { CS_ISO8859_7,    "xft::lang=el"                                },
 
74
  { CS_ISO8859_8,    "xft::lang=he"                                },
 
75
  { CS_ISO8859_9,    "xft::lang=tr"                                },
 
76
  { CS_ISO8859_10,   "xft::lang=se"                                },
 
77
  { CS_ISO8859_11,   "xft::lang=th"                                },
73
78
# endif
74
79
#endif
75
80
 
80
85
  { CS_JIS0208_1990_0, "xft:Kochi Gothic:antialias=false"          },
81
86
  { CS_JIS0208_1990_0, "xft:Sazanami Mincho:antialias=false"       },
82
87
  { CS_JIS0208_1990_0, "xft:Mincho:antialias=false"                },
83
 
  { CS_JIS0208_1990_0, "xft::lang=ja:spacing=100:antialias=false"  },
 
88
  { CS_JIS0208_1990_0, "xft::lang=ja:antialias=false"              },
84
89
# endif
85
90
  { CS_JIS0201_1976_0, "-*-mincho-*-r-*--*-*-*-*-c-*-jisx0201*-0"  },
86
91
  { CS_JIS0208_1990_0, "-*-mincho-*-r-*--*-*-*-*-c-*-jisx0208*-0"  },
94
99
# if XFT
95
100
  { CS_GBK_0,          "xft:AR PL KaitiM GB"                       },
96
101
  { CS_GBK_0,          "xft:AR PL SungtiL GB"                      },
97
 
  { CS_GBK_0,          "xft::spacing=100:lang=zh"                  },
 
102
  { CS_GBK_0,          "xft::lang=zh"                              },
98
103
  { CS_BIG5_EXT,       "xft:AR PL Mingti2L Big5"                   },
99
104
  { CS_BIG5_EXT,       "xft:AR PL KaitiM Big5"                     },
100
105
  { CS_GB2312_1980_0,  "xft:AR PL KaitiM GB"                       },
101
106
  { CS_GB2312_1980_0,  "xft:AR PL SungtiL GB"                      },
102
 
  { CS_GB2312_1980_0,  "xft::spacing=100:lang=zh"                  },
 
107
  { CS_GB2312_1980_0,  "xft::lang=zh"                              },
103
108
# endif
104
109
  { CS_GBK_0,           "-*-*-*-*-*-*-*-*-*-*-c-*-gbk*-0"          },
105
110
  { CS_BIG5,            "-*-*-*-*-*-*-*-*-*-*-c-*-big5-0"          },
122
127
  { CS_KSC5601_1987_0,  "-*-*-*-*-*-*-*-*-*-*-c-*-ksc5601*"        },
123
128
# if XFT
124
129
  { CS_KSC5601_1987_0,  "xft:Baekmuk Gulim:antialias=false"        },
125
 
  { CS_KSC5601_1987_0,  "xft::spacing=100:lang=ko:antialias=false" },
 
130
  { CS_KSC5601_1987_0,  "xft::lang=ko:antialias=false"             },
126
131
# endif
127
132
#endif
128
133
 
129
 
  // generic font fallback
130
134
  { CS_UNICODE,      "-*-lucidatypewriter-*-*-*-*-*-*-*-*-m-*-iso10646-1" },
131
 
  { CS_UNICODE,      "-*-unifont-*-*-*-*-*-*-*-*-c-*-iso10646-1"   },
132
 
  { CS_UNICODE,      "-*-*-*-r-*-*-*-*-*-*-c-*-iso10646-1"         },
133
 
  { CS_UNICODE,      "-*-*-*-r-*-*-*-*-*-*-m-*-iso10646-1"         },
 
135
  //{ CS_UNICODE,      "-*-unifont-*-*-*-*-*-*-*-*-c-*-iso10646-1"   }, // this gem of a font has actual dotted circles within the combining character glyphs.
134
136
#if XFT
135
 
  { CS_UNICODE,      "xft:Bitstream Vera Sans Mono:antialias=false:autohint=true"},
136
 
  { CS_UNICODE,      "xft:Courier New:antialias=false:autohint=true" },
137
 
  { CS_UNICODE,      "xft:Andale Mono:antialias=false"             },
138
 
  { CS_UNICODE,      "xft:Arial Unicode MS:antialias=false"        },
 
137
  { CS_UNICODE,      "xft:Bitstream Vera Sans Mono:antialias=false:autohint=true" },
 
138
  { CS_UNICODE,      "xft:Courier New:antialias=false:autohint=true"              },
 
139
  { CS_UNICODE,      "xft:Andale Mono:antialias=false:autohint=false"             },
 
140
  { CS_UNICODE,      "xft:Arial Unicode MS:antialias=false:autohint=false"        },
139
141
 
140
 
  // FreeMono is usually uglier than x fonts, so try last only.
 
142
  // FreeMono is usually uglier than x fonts, so try after the others
141
143
  { CS_UNICODE,      "xft:FreeMono:autohint=true"                  },
142
144
#endif
143
145
 
 
146
  // generic font fallback, put this last, as many iso10646 fonts have extents
 
147
  // specified for all glyphs in the range they cover, but most are simply empty
 
148
  //{ CS_UNICODE,      "-*-*-*-r-*-*-*-*-*-*-c-*-iso10646-1"         },
 
149
  //{ CS_UNICODE,      "-*-*-*-r-*-*-*-*-*-*-m-*-iso10646-1"         },
144
150
  { CS_UNKNOWN, 0 }
145
151
};
146
152
 
154
160
 
155
161
#define NUM_EXTENT_TEST_CHARS (sizeof (extent_test_chars) / sizeof (extent_test_chars[0]))
156
162
 
157
 
/////////////////////////////////////////////////////////////////////////////
158
 
 
159
 
#if XFT
160
 
rxvt_drawable::~rxvt_drawable ()
161
 
{
162
 
  if (xftdrawable)
163
 
    XftDrawDestroy (xftdrawable);
164
 
}
165
 
 
166
 
rxvt_drawable::operator XftDraw *()
167
 
{
168
 
  if (!xftdrawable)
169
 
    xftdrawable = XftDrawCreate (display->display, drawable, display->visual, display->cmap);
170
 
 
171
 
  return xftdrawable;
172
 
}
173
 
#endif
174
 
 
175
 
/////////////////////////////////////////////////////////////////////////////
176
 
 
177
 
static void *enc_buf;
178
 
static uint32_t enc_len;
179
 
 
180
 
static inline void *
181
 
get_enc_buf (uint32_t len)
182
 
{
183
 
  if (len > enc_len)
184
 
    {
185
 
      free (enc_buf);
186
 
      enc_buf = malloc (len);
187
 
      enc_len = len;
188
 
    }
189
 
 
190
 
  return enc_buf;
191
 
}
 
163
#define dTermDisplay Display *disp = term->dpy
 
164
#define dTermGC      GC gc = term->gc
 
165
 
 
166
/////////////////////////////////////////////////////////////////////////////
192
167
 
193
168
static const char *
194
169
enc_char (const text_t *text, uint32_t len, codeset cs, bool &zero)
195
170
{
196
 
  uint8_t *buf = (uint8_t *)get_enc_buf (len);
 
171
  uint8_t *buf = rxvt_temp_buf<uint8_t> (len);
 
172
  uint8_t *res = buf;
197
173
 
198
174
  while (len--)
199
175
    {
208
184
      *buf++ = c;
209
185
    }
210
186
 
211
 
  return (const char *)enc_buf;
 
187
  return (const char *)res;
212
188
}
213
189
 
214
190
static const XChar2b *
215
191
enc_xchar2b (const text_t *text, uint32_t len, codeset cs, bool &zero)
216
192
{
217
 
  XChar2b *buf = (XChar2b *)get_enc_buf (len * sizeof (XChar2b));
 
193
  XChar2b *buf = rxvt_temp_buf<XChar2b> (len);
 
194
  XChar2b *res = buf;
218
195
 
219
196
  while (len--)
220
197
    {
231
208
      buf++;
232
209
    }
233
210
 
234
 
  return (XChar2b *)enc_buf;
 
211
  return res;
235
212
}
236
213
 
237
214
/////////////////////////////////////////////////////////////////////////////
238
215
 
 
216
rxvt_font::rxvt_font ()
 
217
: name(0), width(rxvt_fontprop::unset), height(rxvt_fontprop::unset)
 
218
{
 
219
}
 
220
 
239
221
void
240
222
rxvt_font::set_name (char *name)
241
223
{
247
229
}
248
230
 
249
231
void
250
 
rxvt_font::clear_rect (rxvt_drawable &d, int x, int y, int w, int h, int color)
 
232
rxvt_font::clear_rect (rxvt_drawable &d, int x, int y, int w, int h, int color) const
251
233
{
252
 
  if (color == Color_bg)
253
 
    XClearArea (d.display->display, d, x, y, w, h, FALSE);
254
 
  else if (color >= 0)
 
234
  dTermDisplay;
 
235
  dTermGC;
 
236
  
 
237
  if (color < 0 || color == Color_bg)
 
238
    XClearArea (disp, d, x, y, w, h, false);
 
239
  else
255
240
    {
256
241
#if XFT
257
 
      XftDrawRect (d, &r->pix_colors[color].c, x, y, w, h);
 
242
      XftDrawRect (d, &term->pix_colors[color].c, x, y, w, h);
258
243
#else
259
 
      XSetForeground (d.display->display, TGC, r->pix_colors[color]);
260
 
      XFillRectangle (d.display->display, d, TGC, x, y, w, h);
 
244
      XSetForeground (disp, gc, term->pix_colors[color]);
 
245
      XFillRectangle (disp, d, gc, x, y, w, h);
261
246
#endif
262
247
    }
263
248
}
264
249
 
 
250
/////////////////////////////////////////////////////////////////////////////
 
251
 
265
252
#include "table/linedraw.h"
266
253
 
267
254
struct rxvt_font_default : rxvt_font {
278
265
    rxvt_fontprop p;
279
266
 
280
267
    p.width = p.height = 1;
 
268
    p.ascent = rxvt_fontprop::unset;
281
269
    p.weight = rxvt_fontprop::medium;
282
270
    p.slant = rxvt_fontprop::roman;
283
271
 
294
282
    return true;
295
283
  }
296
284
 
297
 
  bool has_char (unicode_t unicode, const rxvt_fontprop *prop, bool &careful)
 
285
  bool has_char (unicode_t unicode, const rxvt_fontprop *prop, bool &careful) const
298
286
  {
299
287
    careful = false;
300
288
 
307
295
    if (unicode <= 0x009f)
308
296
      return true;
309
297
 
310
 
    if (unicode >= 0x2500 && unicode <= 0x259f)
 
298
    if (unicode >= 0x2500 && unicode <= 0x259f &&
 
299
        !term->option (Opt_skipBuiltinGlyphs))
311
300
      return true;
312
301
 
313
302
    if (IS_COMPOSE (unicode))
333
322
                         const text_t *text, int len,
334
323
                         int fg, int bg)
335
324
{
336
 
  Display *disp = d.display->display;
337
 
 
338
 
  clear_rect (d, x, y, r->TermWin.fwidth * len, r->TermWin.fheight, bg);
339
 
 
340
 
  XSetForeground (disp, TGC, r->pix_colors[fg]);
 
325
  dTermDisplay;
 
326
  dTermGC;
 
327
 
 
328
  clear_rect (d, x, y, term->fwidth * len, term->fheight, bg);
 
329
 
 
330
  XSetForeground (disp, gc, term->pix_colors[fg]);
341
331
 
342
332
  while (len)
343
333
    {
351
341
        ;
352
342
 
353
343
      int width = text - tp;
354
 
      int fwidth = r->TermWin.fwidth * width;
 
344
      int fwidth = term->fwidth * width;
355
345
 
356
346
      if (0x2500 <= t && t <= 0x259f)
357
347
        {
360
350
          uint32_t *b = a + (offs & 15);
361
351
 
362
352
          int W = fwidth;
363
 
          int H = r->TermWin.fheight;
 
353
          int H = term->fheight;
364
354
 
365
355
          int x_[16];
366
356
          int y_[16];
378
368
 
379
369
          gcv.cap_style = CapButt;
380
370
          gcv.line_width = 0;
381
 
          XChangeGC (disp, TGC, GCLineWidth | GCCapStyle, &gcv);
 
371
          XChangeGC (disp, gc, GCLineWidth | GCCapStyle, &gcv);
382
372
 
383
373
          while (a < b)
384
374
            {
395
385
              switch (op)
396
386
                {
397
387
                  case 0: // line
398
 
                    XDrawLine (disp, d, TGC, x1, y1, x2, y2);
 
388
                    XDrawLine (disp, d, gc, x1, y1, x2, y2);
399
389
                    break;
400
390
 
401
391
                  case 1: // rectangle, possibly stippled
408
398
                        gcv.ts_x_origin = x;
409
399
                        gcv.ts_y_origin = y;
410
400
 
411
 
                        XChangeGC (disp, TGC,
 
401
                        XChangeGC (disp, gc,
412
402
                                   GCFillStyle | GCStipple | GCTileStipXOrigin | GCTileStipYOrigin,
413
403
                                   &gcv);
414
404
                      }
415
405
 
416
 
                    XFillRectangle (disp, d, TGC, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
 
406
                    XFillRectangle (disp, d, gc, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
417
407
 
418
408
                    if (a)
419
409
                      {
420
410
                        XFreePixmap (disp, gcv.stipple);
421
411
                        gcv.stipple = 0;
422
412
                        gcv.fill_style = FillSolid;
423
 
                        XChangeGC (disp, TGC, GCFillStyle, &gcv);
 
413
                        XChangeGC (disp, gc, GCFillStyle, &gcv);
424
414
                      }
425
415
                    break;
426
416
                  case 2: // arc
427
 
                    XDrawArc (disp, d, TGC,
 
417
                    XDrawArc (disp, d, gc,
428
418
                              x1 - W/2, y1 - H/2, W-1, H-1,
429
419
                              (a - 1) * 90*64, (b - 1) * 90*64);
430
420
                    break;
434
424
#if ENABLE_COMBINING
435
425
      else if (IS_COMPOSE (t) && (cc = rxvt_composite[t]))
436
426
        {
 
427
          min_it (width, 2); // we only support wcwidth up to 2
 
428
 
437
429
          text_t chrs[2];
438
 
          width = min (2, width);
439
430
          chrs [1] = NOCHAR;
440
431
 
441
432
          *chrs = cc->c1;
465
456
              break;
466
457
 
467
458
            default:
468
 
              XDrawRectangle (disp, d, TGC, x + 2, y + 2,
469
 
                              fwidth - 4, r->TermWin.fheight - 4);
 
459
              XDrawRectangle (disp, d, gc, x + 2, y + 2,
 
460
                              fwidth - 4, term->fheight - 4);
470
461
          }
471
462
 
472
463
      x += fwidth;
484
475
 
485
476
  bool load (const rxvt_fontprop &prop);
486
477
 
487
 
  bool has_char (unicode_t unicode, const rxvt_fontprop *prop, bool &careful);
 
478
  bool has_char (unicode_t unicode, const rxvt_fontprop *prop, bool &careful) const;
488
479
 
489
480
  void draw (rxvt_drawable &d, int x, int y,
490
481
             const text_t *text, int len,
495
486
  codeset cs;
496
487
  bool enc2b, encm;
497
488
 
498
 
  char *get_property (XFontStruct *f, const char *property, const char *repl) const;
 
489
  char *get_property (XFontStruct *f, Atom property, const char *repl) const;
499
490
  bool set_properties (rxvt_fontprop &p, int height, const char *weight, const char *slant, int avgwidth);
500
491
  bool set_properties (rxvt_fontprop &p, XFontStruct *f);
501
492
  bool set_properties (rxvt_fontprop &p, const char *name);
502
493
};
503
494
 
504
495
char *
505
 
rxvt_font_x11::get_property (XFontStruct *f, const char *property, const char *repl) const
 
496
rxvt_font_x11::get_property (XFontStruct *f, Atom property, const char *repl) const
506
497
{
507
498
  unsigned long value;
508
499
 
509
 
  if (XGetFontProperty (f, XInternAtom (DISPLAY, property, 0), &value))
510
 
    return XGetAtomName (DISPLAY, value);
 
500
  if (XGetFontProperty (f, property, &value))
 
501
    return XGetAtomName (term->dpy, value);
511
502
  else
512
503
    return rxvt_strdup (repl);
513
504
}
523
514
bool
524
515
rxvt_font_x11::set_properties (rxvt_fontprop &p, int height, const char *weight, const char *slant, int avgwidth)
525
516
{
526
 
  p.width  = avgwidth ? (avgwidth + 1) / 10 : (height + 1) / 2;
 
517
  p.width  = width != rxvt_fontprop::unset ? width
 
518
           : avgwidth                      ? (avgwidth + 1) / 10
 
519
                                           : (height + 1) / 2;
527
520
  p.height = height;
 
521
  p.ascent = rxvt_fontprop::unset;
528
522
  p.weight = *weight == 'B' || *weight == 'b' ? rxvt_fontprop::bold : rxvt_fontprop::medium;
529
523
  p.slant  = *slant == 'r' || *slant == 'R' ? rxvt_fontprop::roman : rxvt_fontprop::italic;
530
524
 
537
531
  unsigned long height;
538
532
 
539
533
#if 0
540
 
  if (!XGetFontProperty (f, XInternAtom (DISPLAY, "PIXEL_SIZE", 0), &height))
 
534
  if (!XGetFontProperty (f, XInternAtom (term->dpy, "PIXEL_SIZE", 0), &height))
541
535
    return false;
542
536
#else
543
537
  height = f->ascent + f->descent;
544
538
#endif
545
539
 
546
540
  unsigned long avgwidth;
547
 
  if (!XGetFontProperty (f, XInternAtom (DISPLAY, "AVERAGE_WIDTH", 0), &avgwidth))
 
541
  if (!XGetFontProperty (f, term->xa [XA_AVERAGE_WIDTH], &avgwidth))
548
542
    avgwidth = 0;
549
543
 
550
 
  char *weight = get_property (f, "WEIGHT_NAME", "medium");
551
 
  char *slant  = get_property (f, "SLANT", "r");
 
544
  char *weight = get_property (f, term->xa [XA_WEIGHT_NAME], "medium");
 
545
  char *slant  = get_property (f, term->xa [XA_SLANT], "r");
552
546
 
553
547
  set_properties (p, height, weight, slant, avgwidth);
554
548
 
555
549
  free (weight);
556
550
  free (slant);
557
551
 
 
552
  p.ascent = f->ascent;
 
553
 
558
554
  return true;
559
555
}
560
556
 
561
557
bool
562
558
rxvt_font_x11::set_properties (rxvt_fontprop &p, const char *name)
563
559
{
 
560
  dTermDisplay;
564
561
  int slashes = 0;
565
562
  const char *comp[13];
566
563
 
578
575
      && (*comp[11] >= '0' && *comp[11] <= '9'))
579
576
    return set_properties (p, atoi (comp[6]), comp[2], comp[3], atoi (comp[11]));
580
577
 
581
 
  XFontStruct *f = XLoadQueryFont (DISPLAY, name);
 
578
  XFontStruct *f = XLoadQueryFont (disp, name);
582
579
 
583
580
  if (f)
584
581
    {
586
583
      // (e.g. if the user did xset fp rehash just when we were searching fonts).
587
584
      // in that case, just return garbage.
588
585
      bool ret = set_properties (p, f);
589
 
      XFreeFont (DISPLAY, f);
 
586
      XFreeFont (disp, f);
590
587
      return ret;
591
588
    }
592
589
  else
634
631
bool
635
632
rxvt_font_x11::load (const rxvt_fontprop &prop)
636
633
{
637
 
  Display *disp = DISPLAY;
 
634
  dTermDisplay;
638
635
 
639
636
  clear ();
640
637
 
653
650
          if (!f)
654
651
            return false;
655
652
 
656
 
          char *new_name = get_property (f, "FONT", name);
 
653
          char *new_name = get_property (f, XA_FONT, name);
657
654
 
658
655
          if (new_name)
659
656
            set_name (new_name);
719
716
      if (replace_field (fname, list[i], 6, '0', field_str))
720
717
        diff += 10; // slightly penalize scalable fonts
721
718
      else if (replace_field (fname, list[i], 11, '0', "0"))
722
 
        diff += 300; // more heavily penalize what looks like scaled bitmap fotns
 
719
        diff += 300; // more heavily penalize what looks like scaled bitmap fonts
723
720
 
724
721
      if (!set_properties (p, fname))
725
722
        continue;
772
769
  if (!f)
773
770
    return false;
774
771
 
775
 
  char *registry = get_property (f, "CHARSET_REGISTRY", 0);
776
 
  char *encoding = get_property (f, "CHARSET_ENCODING", 0);
 
772
  char *registry = get_property (f, term->xa [XA_CHARSET_REGISTRY], 0);
 
773
  char *encoding = get_property (f, term->xa [XA_CHARSET_ENCODING], 0);
777
774
 
778
775
  if (registry && encoding)
779
776
    {
784
781
    }
785
782
  else
786
783
    {
787
 
      const char *charset = get_property (f, "FONT", 0);
 
784
      const char *charset = get_property (f, XA_FONT, 0);
788
785
 
789
786
      if (!charset)
790
787
        charset = name;
809
806
  slow = false;
810
807
 
811
808
#if 1 // only used for slow detection, TODO optimize
812
 
  if (f->min_bounds.width == f->max_bounds.width)
813
 
    width = f->min_bounds.width;
814
 
  else if (f->per_char == NULL)
 
809
  if (f->min_bounds.width == f->max_bounds.width || !f->per_char)
815
810
    width = f->max_bounds.width;
816
811
  else
817
812
    {
837
832
 
838
833
  for (uint16_t *t = extent_test_chars + NUM_EXTENT_TEST_CHARS; t-- > extent_test_chars; )
839
834
    {
840
 
      if (cs != CS_UNICODE
841
 
          && *t > 0x100
842
 
          && FROM_UNICODE (cs, *t) == NOCHAR)
 
835
      if (FROM_UNICODE (cs, *t) == NOCHAR)
843
836
        continue;
844
837
 
845
838
      // ignore characters we wouldn't use anyways
853
846
      int dir_ret, asc_ret, des_ret;
854
847
      XTextExtents16 (f, &ch, 1, &dir_ret, &asc_ret, &des_ret, &g);
855
848
 
856
 
      int wcw = wcwidth (*t); if (wcw > 0) g.width = g.width / wcw;
 
849
      int wcw = WCWIDTH (*t);
 
850
      if (wcw > 0) g.width = (g.width + wcw - 1) / wcw;
857
851
 
858
 
      if (width  < g.width)  width  = g.width;
 
852
      if (width < g.width) width = g.width;
859
853
    }
860
854
 
861
855
  if (cs == CS_UNKNOWN)
882
876
{
883
877
  if (f)
884
878
    {
885
 
      XFreeFont (DISPLAY, f);
 
879
      XFreeFont (term->dpy, f);
886
880
      f = 0;
887
881
    }
888
882
}
889
883
 
890
884
bool
891
 
rxvt_font_x11::has_char (unicode_t unicode, const rxvt_fontprop *prop, bool &careful)
 
885
rxvt_font_x11::has_char (unicode_t unicode, const rxvt_fontprop *prop, bool &careful) const
892
886
{
893
887
  uint32_t ch = FROM_UNICODE (cs, unicode);
894
888
 
935
929
  if (!prop || prop->width == rxvt_fontprop::unset)
936
930
    return true;
937
931
 
938
 
  // check character against base font bounding box
939
 
  int w = xcs->width;
940
 
  int wcw = wcwidth (unicode);
941
 
  if (wcw > 0) w /= wcw;
942
 
 
943
 
  careful = w > prop->width;
944
 
  if (careful && w > prop->width * MAX_OVERLAP >> 2)
 
932
  // check wether character overlaps previous/next character
 
933
  int w = xcs->rbearing - xcs->lbearing;
 
934
  int wcw = max (WCWIDTH (unicode), 1);
 
935
 
 
936
  careful = xcs->lbearing < 0 || xcs->rbearing > prop->width * wcw;
 
937
 
 
938
  if (careful && !OVERLAP_OK (w, wcw, prop))
945
939
    return false;
946
940
 
947
941
  return true;
957
951
  // yet we are trying to be perfect /.
958
952
  // but the result still isn't perfect /.
959
953
 
 
954
  dTermDisplay;
 
955
  dTermGC;
 
956
 
960
957
  bool slow = this->slow
961
 
              || width != r->TermWin.fwidth
962
 
              || height != r->TermWin.fheight;
 
958
              || width  != term->fwidth
 
959
              || height != term->fheight;
963
960
 
964
 
  int base = ascent; // sorry, incorrect: r->TermWin.fbase;
 
961
  int base = ascent; // sorry, incorrect: term->fbase;
965
962
 
966
963
  XGCValues v;
967
 
  v.foreground = r->pix_colors[fg];
 
964
  v.foreground = term->pix_colors[fg];
968
965
  v.font = f->fid;
969
966
 
970
967
  if (enc2b)
973
970
 
974
971
      if (bg == Color_bg && !slow)
975
972
        {
976
 
          v.background = r->pix_colors[bg];
977
 
          XChangeGC (d.display->display, TGC, GCForeground | GCBackground | GCFont, &v);
978
 
          XDrawImageString16 (d.display->display, d, TGC, x, y + base, xc, len);
 
973
          v.background = term->pix_colors[bg];
 
974
          XChangeGC (disp, gc, GCForeground | GCBackground | GCFont, &v);
 
975
          XDrawImageString16 (disp, d, gc, x, y + base, xc, len);
979
976
        }
980
977
      else
981
978
        {
982
 
          clear_rect (d, x, y, r->TermWin.fwidth * len, r->TermWin.fheight, bg);
 
979
          clear_rect (d, x, y, term->fwidth * len, term->fheight, bg);
983
980
 
984
 
          XChangeGC (d.display->display, TGC, GCForeground | GCFont, &v);
 
981
          XChangeGC (disp, gc, GCForeground | GCFont, &v);
985
982
          
986
983
          if (slow)
987
984
            {
988
985
              do
989
986
                {
990
987
                  if (xc->byte1 || xc->byte2)
991
 
                    XDrawString16 (d.display->display, d, TGC, x, y + base, xc, 1);
 
988
                    XDrawString16 (disp, d, gc, x, y + base, xc, 1);
992
989
 
993
 
                  x += r->TermWin.fwidth;
 
990
                  x += term->fwidth;
994
991
                  xc++; len--;
995
992
                }
996
993
              while (len);
997
994
            }
998
995
          else
999
 
            XDrawString16 (d.display->display, d, TGC, x, y + base, xc, len);
 
996
            XDrawString16 (disp, d, gc, x, y + base, xc, len);
1000
997
        }
1001
998
    }
1002
999
  else
1005
1002
 
1006
1003
      if (bg == Color_bg && !slow)
1007
1004
        {
1008
 
          v.background = r->pix_colors[bg];
1009
 
          XChangeGC (d.display->display, TGC, GCForeground | GCBackground | GCFont, &v);
1010
 
          XDrawImageString (d.display->display, d, TGC, x, y + base, xc, len);
 
1005
          v.background = term->pix_colors[bg];
 
1006
          XChangeGC (disp, gc, GCForeground | GCBackground | GCFont, &v);
 
1007
          XDrawImageString (disp, d, gc, x, y + base, xc, len);
1011
1008
        }
1012
1009
      else
1013
1010
        {
1014
 
          clear_rect (d, x, y, r->TermWin.fwidth * len, r->TermWin.fheight, bg);
 
1011
          clear_rect (d, x, y, term->fwidth * len, term->fheight, bg);
1015
1012
 
1016
 
          XChangeGC (d.display->display, TGC, GCForeground | GCFont, &v);
 
1013
          XChangeGC (disp, gc, GCForeground | GCFont, &v);
1017
1014
          
1018
1015
          if (slow)
1019
1016
            {
1020
1017
              do
1021
1018
                {
1022
1019
                  if (*xc)
1023
 
                    XDrawString (d.display->display, d, TGC, x, y + base, xc, 1);
 
1020
                    XDrawString (disp, d, gc, x, y + base, xc, 1);
1024
1021
 
1025
 
                  x += r->TermWin.fwidth;
 
1022
                  x += term->fwidth;
1026
1023
                  xc++; len--;
1027
1024
                }
1028
1025
              while (len);
1029
1026
            }
1030
1027
          else
1031
 
            XDrawString (d.display->display, d, TGC, x, y + base, xc, len);
 
1028
            XDrawString (disp, d, gc, x, y + base, xc, len);
1032
1029
        }
1033
1030
    }
1034
1031
}
1050
1047
             const text_t *text, int len,
1051
1048
             int fg, int bg);
1052
1049
 
1053
 
  bool has_char (unicode_t unicode, const rxvt_fontprop *prop, bool &carefull);
 
1050
  bool has_char (unicode_t unicode, const rxvt_fontprop *prop, bool &carefull) const;
1054
1051
 
1055
1052
protected:
1056
1053
  XftFont *f;
1061
1058
{
1062
1059
  if (f)
1063
1060
    {
1064
 
      XftFontClose (DISPLAY, f);
 
1061
      XftFontClose (term->dpy, f);
1065
1062
      f = 0;
1066
1063
    }
1067
1064
}
1075
1072
 
1076
1073
  p.width  = width;
1077
1074
  p.height = height;
 
1075
  p.ascent = ascent;
1078
1076
  p.weight = face->style_flags & FT_STYLE_FLAG_BOLD
1079
1077
               ? rxvt_fontprop::bold : rxvt_fontprop::medium;
1080
1078
  p.slant  = face->style_flags & FT_STYLE_FLAG_ITALIC
1088
1086
bool
1089
1087
rxvt_font_xft::load (const rxvt_fontprop &prop)
1090
1088
{
1091
 
  Display *disp = DISPLAY;
 
1089
  dTermDisplay;
1092
1090
 
1093
1091
  clear ();
1094
1092
 
1125
1123
  set_name ((char *)FcNameUnparse (p));
1126
1124
 
1127
1125
  XftResult result;
1128
 
  FcPattern *match = XftFontMatch (disp, r->display->screen, p, &result);
 
1126
  FcPattern *match = XftFontMatch (disp, term->display->screen, p, &result);
1129
1127
 
1130
1128
  FcPatternDestroy (p);
1131
1129
 
1156
1154
 
1157
1155
      XftUnlockFace (f);
1158
1156
 
 
1157
      int glheight = height;
 
1158
 
1159
1159
      for (uint16_t *t = extent_test_chars + NUM_EXTENT_TEST_CHARS; t-- > extent_test_chars; )
1160
1160
        {
1161
1161
          FcChar16 ch = *t;
1173
1173
          XGlyphInfo g;
1174
1174
          XftTextExtents16 (disp, f, &ch, 1, &g);
1175
1175
 
1176
 
          int wcw = wcwidth (ch);
1177
 
          if (wcw > 0) g.width = g.width / wcw;
1178
 
 
1179
 
          if (width  < g.width)  width  = g.width;
1180
 
          if (height < g.height) height = g.height;
 
1176
          g.width -= g.x;
 
1177
 
 
1178
          int wcw = WCWIDTH (ch);
 
1179
          if (wcw > 0) g.width = (g.width + wcw - 1) / wcw;
 
1180
 
 
1181
          if (width    < g.width       ) width    = g.width;
 
1182
          if (height   < g.height      ) height   = g.height;
 
1183
          if (glheight < g.height - g.y) glheight = g.height - g.y;
 
1184
        }
 
1185
 
 
1186
      if (!width)
 
1187
        {
 
1188
          rxvt_warn ("unable to calculate font width for '%s', ignoring.\n", name);
 
1189
 
 
1190
          XftFontClose (disp, f);
 
1191
          f = 0;
 
1192
 
 
1193
          success = false;
 
1194
          break;
1181
1195
        }
1182
1196
 
1183
1197
      if (prop.height == rxvt_fontprop::unset
1184
 
          || height <= prop.height
 
1198
          || (height <= prop.height && glheight <= prop.height)
1185
1199
          || height <= 2
1186
1200
          || !scalable)
1187
1201
        break;
1198
1212
      else
1199
1213
        ftheight = prop.height - 1;
1200
1214
 
1201
 
        XftFontClose (disp, f);
1202
 
        FcPatternDel (match, FC_PIXEL_SIZE);
1203
 
        FcPatternAddInteger (match, FC_PIXEL_SIZE, ftheight);
 
1215
      XftFontClose (disp, f);
 
1216
      FcPatternDel (match, FC_PIXEL_SIZE);
 
1217
      FcPatternAddInteger (match, FC_PIXEL_SIZE, ftheight);
1204
1218
    }
1205
1219
 
1206
1220
  FcPatternDestroy (match);
1217
1231
}
1218
1232
 
1219
1233
bool
1220
 
rxvt_font_xft::has_char (unicode_t unicode, const rxvt_fontprop *prop, bool &careful)
 
1234
rxvt_font_xft::has_char (unicode_t unicode, const rxvt_fontprop *prop, bool &careful) const
1221
1235
{
1222
1236
  careful = false;
1223
1237
 
1224
 
  if (!XftCharExists (DISPLAY, f, unicode))
 
1238
  if (!XftCharExists (term->dpy, f, unicode))
1225
1239
    return false;
1226
1240
 
1227
1241
  if (!prop || prop->width == rxvt_fontprop::unset)
1230
1244
  // check character against base font bounding box
1231
1245
  FcChar32 ch = unicode;
1232
1246
  XGlyphInfo g;
1233
 
  XftTextExtents32 (DISPLAY, f, &ch, 1, &g);
1234
 
 
1235
 
  int w = g.width;
1236
 
  int wcw = wcwidth (unicode);
1237
 
  if (wcw > 0) w /= wcw;
1238
 
 
1239
 
  careful = w > prop->width;
1240
 
  if (careful && w > prop->width * MAX_OVERLAP >> 2)
 
1247
  XftTextExtents32 (term->dpy, f, &ch, 1, &g);
 
1248
 
 
1249
  int w = g.width - g.x;
 
1250
  int wcw = max (WCWIDTH (unicode), 1);
 
1251
 
 
1252
  careful = g.x > 0 || w > prop->width * wcw;
 
1253
 
 
1254
  if (careful && !OVERLAP_OK (w, wcw, prop))
 
1255
    return false;
 
1256
 
 
1257
  // this weeds out _totally_ broken fonts, or glyphs
 
1258
  if (!OVERLAP_OK (g.xOff, wcw, prop))
1241
1259
    return false;
1242
1260
 
1243
1261
  return true;
1248
1266
                     const text_t *text, int len,
1249
1267
                     int fg, int bg)
1250
1268
{
1251
 
  clear_rect (d, x, y, r->TermWin.fwidth * len, r->TermWin.fheight, bg);
1252
 
 
1253
 
  int base = ascent; // should be fbase, but that is incorrect
1254
 
 
1255
1269
  XGlyphInfo extents;
1256
 
  FcChar32 *enc = (FcChar32 *) get_enc_buf (len * sizeof (FcChar32));
1257
 
  FcChar32 *ep = enc;
1258
 
  int ewidth = 0;
1259
 
  int xoff = 0;
 
1270
  XftGlyphSpec *enc = (XftGlyphSpec *)rxvt_temp_buf (len * sizeof (XftGlyphSpec));
 
1271
  XftGlyphSpec *ep = enc;
 
1272
 
 
1273
  dTermDisplay;
 
1274
  dTermGC;
 
1275
 
 
1276
  int w = term->fwidth * len;
 
1277
  int h = term->fheight;
 
1278
 
 
1279
  bool buffered = bg >= 0                         // we don't use a transparent bg
 
1280
#ifndef FORCE_UNBUFFERED_XFT
 
1281
# if defined(XPM_BACKGROUND) || defined(TRANSPARENT)
 
1282
                  || !term->am_transparent        // we aren't transparent
 
1283
                  || term->am_pixmap_trans        // we have a pixmap
 
1284
# endif
 
1285
#endif
 
1286
                  ;
 
1287
 
 
1288
  // cut trailing spaces
 
1289
  while (len && text [len - 1] == ' ')
 
1290
    len--;
 
1291
 
 
1292
  int x_ = buffered ? 0 : x;
 
1293
  int y_ = buffered ? 0 : y;
1260
1294
 
1261
1295
  while (len)
1262
1296
    {
1263
 
      int cwidth = r->TermWin.fwidth;
 
1297
      int cwidth = term->fwidth;
1264
1298
      FcChar32 fc = *text++; len--;
1265
 
      FT_UInt gl;
1266
1299
 
1267
1300
      while (len && *text == NOCHAR)
1268
 
        text++, len--, cwidth += r->TermWin.fwidth;
 
1301
        text++, len--, cwidth += term->fwidth;
1269
1302
      
1270
 
      gl = XftCharIndex (d.display->display, f, fc);
1271
 
      XftGlyphExtents (d.display->display, f, &gl, 1, &extents);
1272
 
 
1273
 
      if (extents.xOff != cwidth && ep != enc)
1274
 
        {
1275
 
          if (xoff > ewidth) xoff = ewidth;
1276
 
          XftDrawGlyphs (d, &r->pix_colors[fg].c, f,
1277
 
                         x + (ewidth - xoff >> 1),
1278
 
                         y + base, enc, ep - enc);
1279
 
          x += ewidth;
1280
 
 
1281
 
          ep = enc;
1282
 
          ewidth = 0;
1283
 
          xoff = 0;
1284
 
        }
1285
 
 
1286
 
      if (fc == ' ' && ep == enc) // skip leading spaces
1287
 
        {
1288
 
          x += cwidth;
1289
 
          continue;
1290
 
        }
1291
 
 
 
1303
      if (fc != ' ') // skip spaces
 
1304
        {
 
1305
          FT_UInt glyph = XftCharIndex (disp, f, fc);
 
1306
          XftGlyphExtents (disp, f, &glyph, 1, &extents);
 
1307
 
 
1308
          ep->glyph = glyph;
 
1309
          ep->x = x_ + (cwidth - extents.xOff >> 1);
 
1310
          ep->y = y_ + ascent;
 
1311
 
 
1312
          if (extents.xOff == 0)
 
1313
            ep->x = x_ + cwidth;
 
1314
 
 
1315
          ep++;
 
1316
        }
 
1317
 
 
1318
      x_ += cwidth;
 
1319
    }
 
1320
 
 
1321
  if (buffered)
 
1322
    {
 
1323
      if (ep != enc)
 
1324
        {
 
1325
          rxvt_drawable &d2 = d.screen->scratch_drawable (w, h);
 
1326
 
 
1327
          if (0)
 
1328
            ;
 
1329
#ifdef TRANSPARENT
 
1330
          else if (bg < 0 && term->am_pixmap_trans)
 
1331
            XCopyArea (disp, term->pixmap, d2, gc,
 
1332
                       x + term->window_vt_x, y + term->window_vt_y,
 
1333
                       w, h, 0, 0);
 
1334
#endif
 
1335
#ifdef XPM_BACKGROUND
 
1336
          else if (bg < 0 && term->bgPixmap.pixmap)
 
1337
            {
 
1338
              XGCValues gcv;
 
1339
 
 
1340
              gcv.fill_style  = FillTiled;
 
1341
              gcv.tile        = term->pixmap;
 
1342
              gcv.ts_x_origin = -x;
 
1343
              gcv.ts_y_origin = -y;
 
1344
 
 
1345
              GC gc2 = XCreateGC (disp, d2,
 
1346
                                  GCTile | GCTileStipXOrigin | GCTileStipYOrigin | GCFillStyle,
 
1347
                                  &gcv);
 
1348
 
 
1349
              XFillRectangle (disp, d2, gc2, 0, 0, w, h);
 
1350
 
 
1351
              XFreeGC (disp, gc2);
 
1352
            }
 
1353
#endif
 
1354
          else
 
1355
            XftDrawRect (d2, &term->pix_colors[bg].c, 0, 0, w, h);
 
1356
 
 
1357
          XftDrawGlyphSpec (d2, &term->pix_colors[fg].c, f, enc, ep - enc);
 
1358
          XCopyArea (disp, d2, d, gc, 0, 0, w, h, x, y);
 
1359
        }
1292
1360
      else
1293
 
        {
1294
 
          *ep++ = gl;
1295
 
          ewidth += cwidth;
1296
 
          xoff += extents.xOff;
1297
 
        }
 
1361
        clear_rect (d, x, y, w, h, bg);
1298
1362
    }
1299
 
 
1300
 
  if (ep != enc)
 
1363
  else
1301
1364
    {
1302
 
      if (xoff > ewidth) xoff = ewidth;
1303
 
      XftDrawGlyphs (d, &r->pix_colors[fg].c, f,
1304
 
                     x + (ewidth - xoff >> 1),
1305
 
                     y + base, enc, ep - enc);
 
1365
      clear_rect (d, x, y, w, h, bg);
 
1366
      XftDrawGlyphSpec (d, &term->pix_colors[fg].c, f, enc, ep - enc);
1306
1367
    }
1307
1368
}
 
1369
 
1308
1370
#endif
1309
1371
 
1310
1372
/////////////////////////////////////////////////////////////////////////////
1311
1373
 
1312
 
rxvt_fontset::rxvt_fontset (rxvt_t r)
1313
 
: r (r), fontdesc (0)
 
1374
rxvt_fontset::rxvt_fontset (rxvt_term *term)
 
1375
: fontdesc (0), term (term)
1314
1376
{
1315
1377
  clear ();
1316
1378
}
1323
1385
void
1324
1386
rxvt_fontset::clear ()
1325
1387
{
1326
 
  prop.width = prop.height = prop.weight = prop.slant
 
1388
  prop.width = prop.height = prop.ascent = prop.weight = prop.slant
1327
1389
    = rxvt_fontprop::unset;
1328
1390
 
1329
1391
  for (rxvt_font **i = fonts.begin (); i != fonts.end (); i++)
1364
1426
  else
1365
1427
    f = new rxvt_font_x11;
1366
1428
 
1367
 
  f->set_term (r);
 
1429
  f->set_term (term);
1368
1430
  f->set_name (strdup (name));
1369
1431
 
1370
1432
  f->cs = cs;
1506
1568
 
1507
1569
          if (!realize_font (i))
1508
1570
            goto next_font;
 
1571
 
 
1572
          if (prop.ascent != rxvt_fontprop::unset)
 
1573
            max_it (f->ascent, prop.ascent);
1509
1574
        }
1510
1575
 
1511
1576
      if (f->cs == CS_UNKNOWN)
1554
1619
              //FcPatternAddBool    (p, FC_ANTIALIAS, 1);
1555
1620
 
1556
1621
              XftResult result;
1557
 
              FcPattern *match = XftFontMatch (DISPLAY, r->display->screen, p, &result);
 
1622
              FcPattern *match = XftFontMatch (term->dpy, term->display->screen, p, &result);
1558
1623
 
1559
1624
              FcPatternDestroy (p);
1560
1625