--- rxvt-unicode/src/rxvtfont.C 2010/03/31 13:14:50 1.159 +++ rxvt-unicode/src/rxvtfont.C 2012/01/19 13:33:43 1.185 @@ -1,7 +1,7 @@ /*----------------------------------------------------------------------* * File: rxvtfont.C *----------------------------------------------------------------------* - * Copyright (c) 2003-2008 Marc Lehmann + * Copyright (c) 2003-2008 Marc Lehmann * - original version. * * This program is free software; you can redistribute it and/or modify @@ -24,10 +24,14 @@ #include "rxvtutil.h" #include "rxvtfont.h" -#include +#include #include +#if XFT +# include +#endif + #define MAX_OVERLAP_ROMAN (8 + 2) // max. character width in 8ths of the base width #define MAX_OVERLAP_ITALIC (8 + 3) // max. overlap for italic fonts @@ -37,7 +41,7 @@ : ((prop)->width * (wcw) * MAX_OVERLAP_ROMAN + 7) >> 3 \ )) -const struct rxvt_fallback_font { +static const struct rxvt_fallback_font { codeset cs; const char *name; } fallback_fonts[] = { @@ -130,7 +134,6 @@ # endif #endif - { CS_UNICODE, "-*-lucidatypewriter-*-*-*-*-*-*-*-*-m-*-iso10646-1" }, //{ CS_UNICODE, "-*-unifont-*-*-*-*-*-*-*-*-c-*-iso10646-1" }, // this gem of a font has actual dotted circles within the combining character glyphs. #if XFT { CS_UNICODE, "xft:Bitstream Vera Sans Mono:antialias=false:autohint=true" }, @@ -157,8 +160,6 @@ 0x304c, 0x672c, // が本 }; -#define NUM_EXTENT_TEST_CHARS (sizeof (extent_test_chars) / sizeof (extent_test_chars[0])) - #define dTermDisplay Display *disp = term->dpy #define dTermGC GC gc = term->gc @@ -241,7 +242,7 @@ Picture dst; # ifdef HAVE_BG_PIXMAP - if (term->bgPixmap.pixmap + if (term->bg_pixmap && !term->pix_colors[color].is_opaque () && ((dst = XftDrawPicture (d)))) { @@ -450,7 +451,7 @@ chrs [1] = NOCHAR; *chrs = cc->c1; - rxvt_font *f1 = (*fs)[fs->find_font (cc->c1)]; + rxvt_font *f1 = (*fs)[fs->find_font_idx (cc->c1)]; f1->draw (d, x, y, chrs, width, fg, bg); if (cc->c2 != NOCHAR) @@ -461,7 +462,7 @@ *chrs = cc->c2; rxvt_font *f2 = (f1->has_char (cc->c2, 0, careful) && !careful) ? f1 - : (*fs)[fs->find_font (cc->c2)]; + : (*fs)[fs->find_font_idx (cc->c2)]; f2->draw (d, x, y, chrs, width, fg, Color_none); } @@ -484,6 +485,60 @@ } } +struct rxvt_font_overflow : rxvt_font { + struct rxvt_fontset *fs; + + rxvt_font_overflow (rxvt_fontset *fs) + : rxvt_font () + { + this->fs = fs; + } + + rxvt_fontprop properties () + { + rxvt_fontprop p; + + p.width = p.height = 1; + p.ascent = rxvt_fontprop::unset; + p.weight = rxvt_fontprop::medium; + p.slant = rxvt_fontprop::roman; + + return p; + } + + bool load (const rxvt_fontprop &prop, bool force_prop) + { + width = 1; height = 1; + ascent = 1; descent = 0; + + set_name (strdup ("built-in rendition overflow font")); + + return true; + } + + bool has_char (unicode_t unicode, const rxvt_fontprop *prop, bool &careful) const + { + return false; + } + + void draw (rxvt_drawable &d, int x, int y, + const text_t *text, int len, + int fg, int bg) + { + while (len) + { + int fid = fs->find_font_idx (*text); + int w = 1; + while (w < len && text[w] == NOCHAR) + w++; + (*fs)[fid]->draw (d, x, y, text, w, fg, bg); + text += w; + len -= w; + x += term->fwidth * w; + } + } +}; + ///////////////////////////////////////////////////////////////////////////// struct rxvt_font_x11 : rxvt_font { @@ -668,12 +723,12 @@ if (!f) return false; - char *new_name = get_property (f, XA_FONT, name); + char *new_name = get_property (f, XA_FONT, 0); if (new_name) set_name (new_name); else - rxvt_warn ("font '%s' has no FONT property, continuing without.", name); + rxvt_warn ("font '%s' has no FONT property, continuing without.\n", name); XFreeFont (disp, f); f = 0; @@ -740,12 +795,14 @@ diff += 300; // more heavily penalize what looks like scaled bitmap fonts } - if (!set_properties (p, fname)) - continue; - - if (prop.height != rxvt_fontprop::unset - && p.height > prop.height) // weed out too large fonts - continue; + if (!set_properties (p, fname) + // also weed out too large fonts + || (prop.height != rxvt_fontprop::unset + && p.height > prop.height)) + { + free (fname); + continue; + } if (prop.height != rxvt_fontprop::unset) diff += (prop.height - p.height) * 128; if (prop.weight != rxvt_fontprop::unset) diff += abs (prop.weight - p.weight); @@ -761,10 +818,10 @@ // this loop only iterates when the guessed font-size is too small for (;;) { - font_weight *best = fonts + count - 1; + font_weight *best = fonts; - for (font_weight *w = best; w-- > fonts; ) - if (w->diff <= best->diff) + for (font_weight *w = fonts + 1; w < fonts + count; w++) + if (w->diff < best->diff) best = w; if (!best->name @@ -812,7 +869,8 @@ if (cs == CS_UNKNOWN) { - const char *charset = get_property (f, XA_FONT, 0); + char *value = get_property (f, XA_FONT, 0); + const char *charset = value; if (!charset) charset = name; @@ -825,6 +883,8 @@ cs = codeset_from_name (charset); if (cs == CS_UNKNOWN) rxvt_warn ("%s: cannot deduce encoding from font name property \"%s\", ignoring font.\n", name, charset); + + free (value); } if (cs == CS_UNKNOWN) @@ -866,7 +926,7 @@ width = 1; - for (uint16_t *t = extent_test_chars + NUM_EXTENT_TEST_CHARS; t-- > extent_test_chars; ) + for (uint16_t *t = extent_test_chars; t < extent_test_chars + ecb_array_length (extent_test_chars); t++) { if (FROM_UNICODE (cs, *t) == NOCHAR) continue; @@ -912,6 +972,8 @@ bool rxvt_font_x11::has_char (unicode_t unicode, const rxvt_fontprop *prop, bool &careful) const { + careful = false; + uint32_t ch = FROM_UNICODE (cs, unicode); if (ch == NOCHAR) @@ -1163,10 +1225,12 @@ for (;;) { - f = XftFontOpenPattern (disp, FcPatternDuplicate (match)); + p = FcPatternDuplicate (match); + f = XftFontOpenPattern (disp, p); if (!f) { + FcPatternDestroy (p); success = false; break; } @@ -1184,7 +1248,7 @@ int glheight = height; - for (uint16_t *t = extent_test_chars + NUM_EXTENT_TEST_CHARS; t-- > extent_test_chars; ) + for (uint16_t *t = extent_test_chars; t < extent_test_chars + ecb_array_length (extent_test_chars); t++) { FcChar16 ch = *t; @@ -1349,22 +1413,22 @@ #ifdef HAVE_BG_PIXMAP Picture dst = 0; // the only assignment is done conditionally in the following if condition - if (term->bgPixmap.pixmap + if (term->bg_pixmap && (bg == Color_transparent || bg == Color_bg || (bg >= 0 && !term->pix_colors[bg].is_opaque () && ((dst = XftDrawPicture (d2)))))) { int src_x = x, src_y = y; - if (term->bgPixmap.is_parentOrigin ()) + if (term->bg_flags & rxvt_term::BG_IS_TRANSPARENT) { src_x += term->window_vt_x; src_y += term->window_vt_y; } - if (term->bgPixmap.pmap_width >= src_x + w - && term->bgPixmap.pmap_height >= src_y + h) + if (term->bg_pmap_width >= src_x + w + && term->bg_pmap_height >= src_y + h) { - XCopyArea (disp, term->bgPixmap.pixmap, d2, gc, + XCopyArea (disp, term->bg_pixmap, d2, gc, src_x, src_y, w, h, 0, 0); } else @@ -1372,7 +1436,7 @@ XGCValues gcv; gcv.fill_style = FillTiled; - gcv.tile = term->bgPixmap.pixmap; + gcv.tile = term->bg_pixmap; gcv.ts_x_origin = -src_x; gcv.ts_y_origin = -src_y; @@ -1434,7 +1498,7 @@ force_prop = false; for (rxvt_font **i = fonts.begin (); i != fonts.end (); i++) - FONT_UNREF (*i); + (*i)->unref (); for (pagemap **p = fmap.begin (); p != fmap.end (); p++) delete *p; @@ -1446,6 +1510,15 @@ fallback = fallback_fonts; } +void +rxvt_fontset::prepare_font (rxvt_font *font, codeset cs) +{ + font->set_term (term); + + font->cs = cs; + font->loaded = false; +} + rxvt_font * rxvt_fontset::new_font (const char *name, codeset cs) { @@ -1471,11 +1544,8 @@ else f = new rxvt_font_x11; - f->set_term (term); f->set_name (strdup (name)); - - f->cs = cs; - f->loaded = false; + prepare_font (f, cs); return f; } @@ -1483,6 +1553,23 @@ ///////////////////////////////////////////////////////////////////////////// void +rxvt_fontset::push_font (rxvt_font *font) +{ + // the fontCount index is reserved for the overflow font, it is only + // necessary when we get fontCount or more fonts, as they cannot be + // represented in the rendition. + if (fonts.size () == fontCount) + { + rxvt_font *f = new rxvt_font_overflow (this); + + prepare_font (f, CS_UNICODE); + fonts.push_back (f); + } + + fonts.push_back (font); +} + +void rxvt_fontset::add_fonts (const char *desc) { if (desc) @@ -1531,10 +1618,10 @@ memcpy (buf, desc, end - desc); buf[end - desc] = 0; - fonts.push_back (new_font (buf, cs)); + push_font (new_font (buf, cs)); } else - rxvt_warn ("fontset element too long (>511 bytes), ignored."); + rxvt_warn ("fontset element too long (>511 bytes), ignored.\n"); desc = end + 1; } @@ -1569,7 +1656,7 @@ fontdesc = strdup (desc); - fonts.push_back (new_font (0, CS_UNICODE)); + push_font (new_font (0, CS_UNICODE)); realize_font (0); add_fonts (desc); @@ -1588,7 +1675,7 @@ } int -rxvt_fontset::find_font (unicode_t unicode) +rxvt_fontset::find_font_idx (unicode_t unicode) { if (unicode >= 1<<20) return 0; @@ -1624,8 +1711,7 @@ bool careful; if (f->has_char (unicode, &prop, careful)) { - if (careful) - i |= 128; + i = (i << 1) | careful; goto found; } @@ -1636,7 +1722,7 @@ if (fallback->name) { // search through the fallback list - fonts.push_back (new_font (fallback->name, fallback->cs)); + push_font (new_font (fallback->name, fallback->cs)); fallback++; } else @@ -1679,7 +1765,7 @@ char fontname[4096]; snprintf (fontname, sizeof (fontname), "xft:%s", font); - fonts.push_back (new_font (fontname, CS_UNICODE)); + push_font (new_font (fontname, CS_UNICODE)); } free (font);