1 /*--------------------------------*-C-*---------------------------------*;
3 *----------------------------------------------------------------------*
4 * Copyright (c) 2003 Marc Lehmann rxvt@plan9.de>
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
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
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
20 *---------------------------------------------------------------------*/
22 #include "../config.h"
24 #include "defaultfont.h"
28 #define DISPLAY r->Xdisplay
29 #define DRAWABLE r->TermWin.vt
30 #define GC r->TermWin.gc
32 const struct rxvt_fallback_font {
35 } fallback_fonts[] = {
36 { CS_ISO8859_1, "-*-*-*-r-*--*-*-*-*-c-*-iso8859-1" },
37 { CS_ISO8859_15, "-*-*-*-r-*--*-*-*-*-c-*-iso8859-15" },
38 { CS_ISO8859_15, "-*-*-*-r-*--*-*-*-*-c-*-fcd8859-15" },
42 { CS_KOI8_R, "-*-*-*-r-*--*-*-*-*-c-*-koi8-r" },
43 { CS_KOI8_U, "-*-*-*-r-*--*-*-*-*-c-*-koi8-u" },
45 { CS_ISO8859_2, "-*-*-*-r-*--*-*-*-*-c-*-iso8859-2" },
46 { CS_ISO8859_3, "-*-*-*-r-*--*-*-*-*-c-*-iso8859-3" },
47 { CS_ISO8859_4, "-*-*-*-r-*--*-*-*-*-c-*-iso8859-4" },
48 { CS_ISO8859_5, "-*-*-*-r-*--*-*-*-*-c-*-iso8859-5" },
49 { CS_ISO8859_6, "-*-*-*-r-*--*-*-*-*-c-*-iso8859-6" },
50 { CS_ISO8859_7, "-*-*-*-r-*--*-*-*-*-c-*-iso8859-7" },
51 { CS_ISO8859_8, "-*-*-*-r-*--*-*-*-*-c-*-iso8859-8" },
52 { CS_ISO8859_9, "-*-*-*-r-*--*-*-*-*-c-*-iso8859-9" },
53 { CS_ISO8859_10, "-*-*-*-r-*--*-*-*-*-c-*-iso8859-10" },
54 { CS_ISO8859_11, "-*-*-*-r-*--*-*-*-*-c-*-iso8859-11" },
55 { CS_ISO8859_13, "-*-*-*-r-*--*-*-*-*-c-*-iso8859-13" },
56 { CS_ISO8859_14, "-*-*-*-r-*--*-*-*-*-c-*-iso8859-14" },
57 { CS_ISO8859_16, "-*-*-*-r-*--*-*-*-*-c-*-iso8859-16" },
61 #if ENCODING_JP || ENCODING_JP_EXT
63 // prefer xft for complex scripts
64 { CS_UNICODE, "xft:Kochi Gothic:antialias=false" },
66 { CS_JIS0201_1976_0, "-*-mincho-*-r-*--*-*-*-*-c-*-jisx0201*-0" },
67 { CS_JIS0208_1983_0, "-*-mincho-*-r-*--*-*-*-*-c-*-jisx0208*-0" },
68 { CS_JIS0212_1990_0, "-*-mincho-*-r-*--*-*-*-*-c-*-jisx0212*-0" },
71 #if ENCODING_CN || ENCODING_CN_EXT
73 { CS_BIG5_EXT, "xft:AR PL Mingti2L Big5" },
74 { CS_BIG5_EXT, "xft:AR PL KaitiM Big5" },
75 { CS_GB2312_1980_0, "xft:AR PL KaitiM GB" },
76 { CS_GB2312_1980_0, "xft:AR PL SungtiL GB" },
78 { CS_CNS11643_1992_1, "-*-*-*-*-*-*-*-*-*-*-c-*-gb2312*-0" },
79 { CS_CNS11643_1992_1, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-1" },
80 { CS_CNS11643_1992_2, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-2" },
81 { CS_CNS11643_1992_3, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-3" },
82 { CS_CNS11643_1992_4, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-4" },
83 { CS_CNS11643_1992_5, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-5" },
84 { CS_CNS11643_1992_6, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-6" },
85 { CS_CNS11643_1992_7, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-7" },
86 { CS_CNS11643_1992_F, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-f" },
90 { CS_UNICODE, "xft:Andale Mono" },
91 { CS_UNICODE, "xft:Arial Unicode MS" },
93 { CS_UNICODE, "-*-lucidatypewriter-*-*-*-*-*-*-*-*-m-*-iso10646-1" },
94 { CS_UNICODE, "xft:FreeMono" },
95 { CS_UNICODE, "-*-unifont-*-*-*-*-*-*-*-*-c-*-iso10646-1" },
96 { CS_UNICODE, "-*-*-*-r-*-*-*-*-*-*-c-*-iso10646-1" },
97 { CS_UNICODE, "-*-*-*-r-*-*-*-*-*-*-m-*-iso10646-1" },
102 /////////////////////////////////////////////////////////////////////////////
104 static void *enc_buf;
105 static uint32_t enc_len;
108 get_enc_buf (uint32_t len)
113 enc_buf = malloc (len);
120 enc_char (const text_t *text, uint32_t len, codeset cs, bool &zero)
122 uint8_t *buf = (uint8_t *)get_enc_buf (len);
126 uint32_t c = FROM_UNICODE (cs, *text++);
137 return (const char *)enc_buf;
140 static const XChar2b *
141 enc_xchar2b (const text_t *text, uint32_t len, codeset cs, bool &zero)
143 XChar2b *buf = (XChar2b *)get_enc_buf (len * sizeof (XChar2b));
147 uint32_t c = FROM_UNICODE (cs, *text++);
160 return (XChar2b *)enc_buf;
163 /////////////////////////////////////////////////////////////////////////////
166 rxvt_font::clear_rect (int x, int y, int w, int h, int color)
168 if (color == Color_bg)
169 XClearArea (DISPLAY, DRAWABLE, x, y, w, h, FALSE);
172 XSetForeground (DISPLAY, GC, r->PixColors[color]);
173 XFillRectangle (DISPLAY, DRAWABLE, GC, x, y, w, h);
177 static const char *linedraw_cmds[128] = {
178 "1hH", "2hH", "1vV", "2vV",
181 "1HV", "2H1V", "1H2V", "2HV",
184 "1hV", "2h1V", "1h2V", "2hV",
185 "1Hv", "2H1v", "1H2v", "2Hv",
186 "1hv", "2h1v", "1h2v", "2hv",
187 "1HvV", "2H1vV", "1HV2v", "1Hv2V",
190 "1H2vV", "2Hv1V", "2HV1v", "2HvV",
191 "1hvV", "2h1vV", "1hV2v", "1hv2V",
192 "1h2vV", "2hv1V", "1v2hV", "2hvV",
193 "1hHV", "2h1HV", "2H1hV", "2hH1V",
196 "1hH2V", "2hV1H", "1h2HV", "2hHV",
197 "1hHv", "1vH2h", "1hv2H", "1v2hH",
198 "1hH2v", "1H2hv", "1h2Hv", "2hHv",
199 "1hHvV", "1vVH2h", "1hvV2H", "1vV2hH",
202 "1hHV2v", "1hHv2V", "1hH2vV", "1HV2hv",
203 "1hV2Hv", "1Hv2hV", "1hv2HV", "1V2hHv",
204 "1v2hHV", "1H2hvV", "1h2HvV", "2hHvV",
220 0, "1a", "1b", "1ab",
221 "1h", "1v", "1H", "1V",
222 "2h", "2v", "2H", "2V",
223 "1h2H", "1v2V", "1H2h", "1V2v"
228 struct rxvt_font_default : rxvt_font {
229 rxvt_fontprop properties ()
233 p.width = p.height = 1;
234 p.weight = rxvt_fontprop::medium;
235 p.slant = rxvt_fontprop::roman;
240 bool load (const rxvt_fontprop &prop)
242 width = 1; height = 1;
243 ascent = 1; descent = 0;
248 bool has_codepoint (uint32_t unicode)
250 if (unicode <= 0x001f)
252 if (unicode >= 0x0080 && unicode <= 0x009f)
255 if (unicode >= 0x2500 && unicode <= 0x257f
256 && linedraw_cmds[unicode - 0x2500])
261 case ZERO_WIDTH_CHAR:
268 void draw (int x, int y,
269 const text_t *text, int len,
274 rxvt_font_default::draw (int x, int y,
275 const text_t *text, int len,
278 clear_rect (x, y, r->TermWin.fwidth * len, r->TermWin.fheight, bg);
280 XSetForeground (DISPLAY, GC, r->PixColors[fg]);
286 if (t >= 0x2500 & t <= 0x2580 && linedraw_cmds[t - 0x2500])
288 const char *p = linedraw_cmds[t - 0x2500];
290 int x0 = x, x1 = x + r->TermWin.fwidth / 2, x2 = x + r->TermWin.fwidth ;
291 int y0 = y, y1 = y + r->TermWin.fheight / 2, y2 = y + r->TermWin.fheight;
301 XChangeGC (DISPLAY, GC, GCLineWidth, &gcv);
306 XChangeGC (DISPLAY, GC, GCLineWidth, &gcv);
309 case 'h': XDrawLine (DISPLAY, DRAWABLE, GC, x0, y1, x1, y1); break;
310 case 'H': XDrawLine (DISPLAY, DRAWABLE, GC, x1, y1, x2, y1); break;
311 case 'v': XDrawLine (DISPLAY, DRAWABLE, GC, x1, y0, x1, y1); break;
312 case 'V': XDrawLine (DISPLAY, DRAWABLE, GC, x1, y1, x1, y2); break;
313 case 'a': XDrawLine (DISPLAY, DRAWABLE, GC, x0, y2, x2, y0); break;
314 case 'b': XDrawLine (DISPLAY, DRAWABLE, GC, x0, y0, x2, y2); break;
319 XChangeGC (DISPLAY, GC, GCLineWidth, &gcv);
325 case ZERO_WIDTH_CHAR:
328 XDrawRectangle (DISPLAY, DRAWABLE, GC, x + 2, y + 2, r->TermWin.fwidth - 5, r->TermWin.fheight - 5);
331 x += r->TermWin.fwidth;
335 /////////////////////////////////////////////////////////////////////////////
337 struct rxvt_font_x11 : rxvt_font {
338 rxvt_font_x11 () { f = 0; }
342 rxvt_fontprop properties ();
344 bool load (const rxvt_fontprop &prop);
346 bool has_codepoint (uint32_t unicode);
348 void draw (int x, int y,
349 const text_t *text, int len,
356 const char *get_property (XFontStruct *f, const char *property, const char *repl) const;
357 bool set_properties (rxvt_fontprop &p, int height, const char *weight, const char *slant, int avgwidth);
358 bool set_properties (rxvt_fontprop &p, XFontStruct *f);
359 bool set_properties (rxvt_fontprop &p, const char *name);
363 rxvt_font_x11::get_property (XFontStruct *f, const char *property, const char *repl) const
367 if (XGetFontProperty (f, XInternAtom (DISPLAY, property, 0), &value))
368 return XGetAtomName (DISPLAY, value);
374 rxvt_font_x11::properties ()
377 set_properties (p, f);
382 rxvt_font_x11::set_properties (rxvt_fontprop &p, int height, const char *weight, const char *slant, int avgwidth)
384 p.width = avgwidth ? (avgwidth + 1) / 10 : (height + 1) / 2;
386 p.weight = *weight == 'B' || *weight == 'b' ? rxvt_fontprop::bold : rxvt_fontprop::medium;
387 p.slant = *slant == 'r' || *slant == 'R' ? rxvt_fontprop::roman : rxvt_fontprop::italic;
393 rxvt_font_x11::set_properties (rxvt_fontprop &p, XFontStruct *f)
395 const char *weight = get_property (f, "WEIGHT_NAME", "medium");
396 const char *slant = get_property (f, "SLANT", "r");
398 unsigned long height;
399 if (!XGetFontProperty (f, XInternAtom (DISPLAY, "PIXEL_SIZE", 0), &height))
402 unsigned long avgwidth;
403 if (!XGetFontProperty (f, XInternAtom (DISPLAY, "AVERAGE_WIDTH", 0), &avgwidth))
406 return set_properties (p, height, weight, slant, avgwidth);
410 rxvt_font_x11::set_properties (rxvt_fontprop &p, const char *name)
413 const char *comp[12];
415 for (const char *c = name; *c; c++)
418 comp[slashes++] = c + 1;
423 /* can we short-circuit the costly XLoadQueryFont? */
425 && (*comp[ 6] >= '1' && *comp[ 6] <= '9')
426 && (*comp[11] >= '0' && *comp[11] <= '9'))
427 return set_properties (p, atoi (comp[6]), comp[2], comp[3], atoi (comp[11]));
429 XFontStruct *f = XLoadQueryFont (DISPLAY, name);
433 // the font should really exists now. if not, we have a problem
434 // (e.g. if the user did xset fp rehash just when we were searching fonts).
435 // in that case, just return garbage.
436 bool ret = set_properties (p, f);
437 XFreeFont (DISPLAY, f);
444 // fix the size of scalable fonts
446 fix_scalable (char *buf, const char *name, const rxvt_fontprop &prop)
451 for (const char *c = name; *c; c++)
461 if (slashes >= 13 && size[0] == '0')
463 strncpy (buf, name, size - name);
465 buf += sprintf (buf, "%d", prop.height);
466 strcpy (buf, size + 1);
473 rxvt_font_x11::load (const rxvt_fontprop &prop)
479 list = XListFonts (DISPLAY, name, 512, &count);
485 int bestdiff = 0x7fffffff;
486 for (int i = 0; i < count; i++)
490 fix_scalable (fname, list[i], prop);
492 if (!set_properties (p, fname))
495 if (p.height > prop.height) // weed out too large fonts
498 int diff = (prop.height - p.height) * 32
499 + abs (prop.weight - p.weight)
500 + abs (prop.slant - p.slant );
502 if (!name // compare against best found so far
505 set_name (strdup (fname));
510 XFreeFontNames (list);
515 f = XLoadQueryFont (DISPLAY, name);
520 const char *registry = get_property (f, "CHARSET_REGISTRY", 0);
521 const char *encoding = get_property (f, "CHARSET_ENCODING", 0);
523 if (registry && encoding)
526 snprintf (charset, 64, "%s-%s", registry, encoding);
528 cs = codeset_from_name (charset);
532 const char *charset = get_property (f, "FONT", 0);
539 if (*charset++ == '-' && !--count)
542 cs = codeset_from_name (charset);
545 if (cs == CS_UNICODE)
546 cs = CS_UNICODE_16; // X11 can have a max. of 65536 chars per font
548 encm = f->min_byte1 != 0 || f->max_byte1 != 0;
549 enc2b = encm || f->max_char_or_byte2 > 255;
552 descent = f->descent;
553 height = ascent + descent;
557 if (f->min_bounds.width == f->max_bounds.width)
558 width = f->min_bounds.width;
559 else if (f->per_char == NULL)
560 width = f->max_bounds.width;
565 int N = f->max_char_or_byte2 - f->min_char_or_byte2;
568 N += (f->max_byte1 - f->min_byte1)
569 * (f->max_char_or_byte2 - f->min_char_or_byte2 + 1);
573 if (f->per_char[N].width > width)
574 width = f->per_char[N].width;
580 if (cs == CS_UNKNOWN)
582 fprintf (stderr, "unable to deduce codeset, ignoring font '%s'\n", name);
593 rxvt_font_x11::clear ()
597 XFreeFont (DISPLAY, f);
603 rxvt_font_x11::has_codepoint (uint32_t unicode)
605 uint32_t ch = FROM_UNICODE (cs, unicode);
610 /* check wether the character exists in _this_ font. horrible. */
615 unsigned char byte1 = ch >> 8;
616 unsigned char byte2 = ch & 255;
618 if (byte1 < f->min_byte1 || byte1 > f->max_byte1
619 || byte2 < f->min_char_or_byte2 || byte2 > f->max_char_or_byte2)
625 int D = f->max_char_or_byte2 - f->min_char_or_byte2 + 1;
626 int N = (byte1 - f->min_byte1) * D + byte2 - f->min_char_or_byte2;
628 xcs = f->per_char + N;
632 if (ch < f->min_char_or_byte2 || ch > f->max_char_or_byte2)
638 xcs = f->per_char + (ch - f->min_char_or_byte2);
641 if (xcs->lbearing == 0 && xcs->rbearing == 0 && xcs->width == 0
642 && xcs->ascent == 0 && xcs->descent == 0)
649 rxvt_font_x11::draw (int x, int y,
650 const text_t *text, int len,
653 // this looks like a mess /.
654 // and it is a mess /.
655 // yet we are trying to be perfect /.
656 // but the result still isn't perfect /.
658 bool slow = this->slow
659 || width != r->TermWin.fwidth
660 || height != r->TermWin.fheight;
662 int base = r->TermWin.fbase;
665 v.foreground = r->PixColors[fg];
666 v.background = r->PixColors[bg];
671 const XChar2b *xc = enc_xchar2b (text, len, cs, slow);
673 if (bg == Color_bg && !slow)
675 XChangeGC (DISPLAY, GC, GCForeground | GCBackground | GCFont, &v);
676 XDrawImageString16 (DISPLAY, DRAWABLE, GC, x, y + base, xc, len);
680 clear_rect (x, y, r->TermWin.fwidth * len, r->TermWin.fheight, bg);
682 XChangeGC (DISPLAY, GC, GCForeground | GCFont, &v);
688 if (xc->byte1 || xc->byte2)
689 XDrawString16 (DISPLAY, DRAWABLE, GC, x, y + base, xc, 1);
691 x += r->TermWin.fwidth;
697 XDrawString16 (DISPLAY, DRAWABLE, GC, x, y + base, xc, len);
702 const char *xc = enc_char (text, len, cs, slow);
704 if (bg == Color_bg && !slow)
706 XChangeGC (DISPLAY, GC, GCForeground | GCBackground | GCFont, &v);
707 XDrawImageString (DISPLAY, DRAWABLE, GC, x, y + base, xc, len);
711 clear_rect (x, y, r->TermWin.fwidth * len, r->TermWin.fheight, bg);
713 XChangeGC (DISPLAY, GC, GCForeground | GCFont, &v);
720 XDrawString (DISPLAY, DRAWABLE, GC, x, y + base, xc, 1);
722 x += r->TermWin.fwidth;
728 XDrawString (DISPLAY, DRAWABLE, GC, x, y + base, xc, len);
733 /////////////////////////////////////////////////////////////////////////////
738 //#define SWATHBITS (UNIBITS / 2 + 3) // minimum size for "full" tables
742 struct rxvt_font_xft : rxvt_font {
743 rxvt_font_xft () { f = 0; d = 0; }
747 rxvt_fontprop properties ();
749 bool load (const rxvt_fontprop &prop);
751 void draw (int x, int y,
752 const text_t *text, int len,
755 bool has_codepoint (uint32_t unicode);
763 rxvt_font_xft::clear ()
767 XftFontClose (DISPLAY, f);
779 rxvt_font_xft::properties ()
783 FT_Face face = XftLockFace (f);
785 p.width = width; p.height = height;
786 p.weight = face->style_flags & FT_STYLE_FLAG_BOLD ? rxvt_fontprop::bold : rxvt_fontprop::medium;
787 p.slant = face->style_flags & FT_STYLE_FLAG_ITALIC ? rxvt_fontprop::italic : rxvt_fontprop::roman;
795 rxvt_font_xft::load (const rxvt_fontprop &prop)
798 for (int i = 0; i < SWATHCOUNT; i++)
804 FcPattern *p = FcNameParse ((FcChar8 *) name);
811 if (FcPatternGet (p, FC_WEIGHT, 0, &v) != FcResultMatch)
812 FcPatternAddInteger (p, FC_WEIGHT, prop.weight);
814 if (FcPatternGet (p, FC_SLANT, 0, &v) != FcResultMatch)
815 FcPatternAddInteger (p, FC_SLANT, prop.slant);
817 #if 0 // clipping unfortunately destroys our precious double-width-characters
818 // clip width, we can't do better, or can we?
819 if (FcPatternGet (p, FC_CHAR_WIDTH, 0, &v) != FcResultMatch)
820 FcPatternAddInteger (p, FC_CHAR_WIDTH, prop.width);
823 //FcPatternAddBool (p, FC_MINSPACE, 1);
826 FcPattern *match = XftFontMatch (DISPLAY, DefaultScreen (DISPLAY), p, &result);
828 FcPatternDestroy (p);
833 f = XftFontOpenPattern (DISPLAY, match);
837 FcPatternDestroy (match);
841 FT_Face face = XftLockFace (f);
843 slow = !FT_IS_FIXED_WIDTH (face);
852 c = 'i'; XftTextExtents8 (DISPLAY, f, &c, 1, &g1);
853 c = 'W'; XftTextExtents8 (DISPLAY, f, &c, 1, &g2);
855 if (g1.xOff != g2.xOff) // don't simply trust the font
859 ascent = (face->size->metrics.ascender + 63) >> 6;
860 descent = (-face->size->metrics.descender + 63) >> 6;
861 height = ascent + descent;
863 if (height <= prop.height || !prop.height)
868 // take smaller steps near the end
869 if (height > prop.height + 1) ftheight++;
870 if (height > prop.height + 2) ftheight++;
871 if (height > prop.height + 3) ftheight++;
873 FT_Set_Pixel_Sizes (face, 0, ftheight -= height - prop.height);
876 FT_Set_Pixel_Sizes (face, 0, ftheight = prop.height);
885 rxvt_font_xft::has_codepoint (uint32_t unicode)
887 return XftCharExists (DISPLAY, f, unicode);
891 rxvt_font_xft::draw (int x, int y,
892 const text_t *text, int len,
896 d = XftDrawCreate (DISPLAY, DRAWABLE, r->Xvisual, r->Xcmap);
898 if (bg >= 0 && bg != Color_bg)
899 XftDrawRect (d, &r->PixColors[bg].c, x, y, r->TermWin.fwidth * len, r->TermWin.fheight);
901 clear_rect (x, y, r->TermWin.fwidth * len, r->TermWin.fheight, bg);
903 if (!slow && width == r->TermWin.fwidth && 0)
905 if (sizeof (text_t) == sizeof (FcChar16))
906 XftDrawString16 (d, &r->PixColors[fg].c, f, x, y + r->TermWin.fbase, (const FcChar16 *)text, len);
908 XftDrawString32 (d, &r->PixColors[fg].c, f, x, y + r->TermWin.fbase, (const FcChar32 *)text, len);
914 if (*text != NOCHAR && *text != ' ')
916 int fwidth = r->TermWin.fwidth;
917 if (len >= 2 && text[1] == NOCHAR)
921 if (sizeof (text_t) == sizeof (FcChar16))
923 XftTextExtents16 (DISPLAY, f, (const FcChar16 *)text, 1, &extents);
924 XftDrawString16 (d, &r->PixColors[fg].c, f, x + extents.x + (fwidth - extents.width) / 2,
925 y + r->TermWin.fbase, (const FcChar16 *)text, 1);
930 XftTextExtents32 (DISPLAY, f, (const FcChar32 *)text, 1, &extents);
931 XftDrawString32 (d, &r->PixColors[fg].c, f, x + extents.x + (fwidth - extents.width) / 2,
932 y + r->TermWin.fbase, (const FcChar32 *)text, 1);
936 x += r->TermWin.fwidth;
944 /////////////////////////////////////////////////////////////////////////////
946 rxvt_fontset::rxvt_fontset (rxvt_t r)
952 rxvt_fontset::~rxvt_fontset ()
958 rxvt_fontset::clear ()
960 for (rxvt_font **i = fonts.begin (); i != fonts.end(); i++)
965 base_prop.height = 0x7fffffff;
966 base_prop.weight = rxvt_fontprop::medium;
967 base_prop.slant = rxvt_fontprop::roman;
969 fallback = fallback_fonts;
973 rxvt_fontset::new_font (const char *name, codeset cs)
980 f = new rxvt_font_default;
983 else if (!strncmp (name, "xft:", 4))
986 f = new rxvt_font_xft;
989 else if (!strncmp (name, "x:", 2))
992 f = new rxvt_font_x11;
995 f = new rxvt_font_x11;
998 f->set_name (strdup (name));
1006 /////////////////////////////////////////////////////////////////////////////
1009 rxvt_fontset::add_fonts (const char *desc)
1018 while (*desc <= ' ') desc++;
1022 fprintf (stderr, "extra font parameters not yet supported, skipping.\n");
1024 //const char *extra = desc++; // not yet used
1026 desc = strchr (desc, ']');
1030 fprintf (stderr, "ERROR: opening '[' without closing ']' in font specification.\n");
1035 while (*desc <= ' ') desc++;
1038 end = strchr (desc, ',');
1040 end = desc + strlen (desc);
1042 if (end - desc < 511)
1044 strncpy (buf, desc, end - desc);
1045 buf[end - desc] = 0;
1047 fonts.push_back (new_font (buf, CS_UNICODE));
1057 rxvt_fontset::realize_font (int i)
1059 if (fonts[i]->loaded)
1062 fonts[i]->loaded = true;
1064 if (!fonts[i]->load (base_prop))
1066 fonts[i]->cs = CS_UNKNOWN;
1074 rxvt_fontset::populate (const char *desc)
1078 fonts.push_back (new_font (0, CS_UNICODE));
1086 // we currently need a base-font, no matter what
1087 if ((int)fonts.size () <= base_id || !realize_font (base_id))
1089 puts ("unable to load specified font(s), falling back to 'fixed'\n");
1090 add_fonts ("fixed");
1091 base_id = fonts.size () - 1;
1094 if ((int)fonts.size () <= base_id || !realize_font (base_id))
1096 fprintf (stderr, "unable to load a base font, please provide one using -fn fontname\n");
1100 base_prop = fonts[base_id]->properties ();
1104 rxvt_fontset::find_font (uint32_t unicode)
1106 for (unsigned int i = 0; i < fonts.size (); i++)
1108 rxvt_font *f = fonts[i];
1112 if (FROM_UNICODE (f->cs, unicode) == NOCHAR)
1115 if (!realize_font (i))
1119 if (f->cs != CS_UNKNOWN && f->has_codepoint (unicode))
1123 if (i == fonts.size () - 1 && fallback->name)
1125 fonts.push_back (new_font (fallback->name, fallback->cs));
1131 return 0; /* we must return SOME font */