--- rxvt-unicode/src/rxvtfont.C 2021/06/19 09:13:51 1.213 +++ rxvt-unicode/src/rxvtfont.C 2021/08/26 03:58:29 1.221 @@ -136,10 +136,10 @@ //{ 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" }, - { CS_UNICODE, "xft:Courier New:antialias=false:autohint=true" }, - { CS_UNICODE, "xft:Andale Mono:antialias=false:autohint=false" }, - { CS_UNICODE, "xft:Arial Unicode MS:antialias=false:autohint=false" }, + { CS_UNICODE, "xft:DejaVu Sans Mono:antialias=false:autohint=true" }, + { CS_UNICODE, "xft:Courier New:antialias=false:autohint=true" }, + { CS_UNICODE, "xft:Andale Mono:antialias=false:autohint=false" }, + { CS_UNICODE, "xft:Arial Unicode MS:antialias=false:autohint=false" }, // FreeMono is usually uglier than x fonts, so try after the others { CS_UNICODE, "xft:FreeMono:autohint=true" }, @@ -1139,6 +1139,17 @@ struct rxvt_font_xft : rxvt_font { +#if XFT_CHAR_CACHE + // we cache the qascii range xoffsets in the name of speed, + // expecting terminals to deal mostly with these characters + // we also assume the xoff always fits into uint8_t, + // which is questionable, but let's see... + // also, it is uncomfortably big, due to the uints. + enum { char_cache_min = 0x20, char_cache_max = 0x7e }; + uint8_t xoff_cache [char_cache_max - char_cache_min + 1]; + FT_UInt glyph_cache [char_cache_max - char_cache_min + 1]; +#endif + rxvt_font_xft () { f = 0; @@ -1254,6 +1265,16 @@ FT_Face face = XftLockFace (f); + // fuck me plenty: XftLockFace can actually return 0. try not to crash. + // we also assume blindly that if the first lock succeeeds, then subsequent + // locks will also succeed. + if (!face) + { + XftFontClose (disp, f); + success = false; + break; + } + ascent = (face->size->metrics.ascender + 63) >> 6; descent = (-face->size->metrics.descender + 63) >> 6; height = max (ascent + descent, (face->size->metrics.height + 63) >> 6); @@ -1332,6 +1353,19 @@ } #endif +#if XFT_CHAR_CACHE + // populate char cache + for (FcChar16 ch = char_cache_min; ch <= char_cache_max; ++ch) + { + FT_UInt glyph = XftCharIndex (disp, f, ch); + glyph_cache [ch - char_cache_min] = glyph; + + XGlyphInfo g; + XftGlyphExtents (disp, f, &glyph, 1, &g); + xoff_cache [ch - char_cache_min] = g.xOff; + } +#endif + return success; } @@ -1365,9 +1399,15 @@ XGlyphInfo g; XftTextExtents32 (term->dpy, f, &chr, 1, &g); + int cwidth = prop->width * wcw; + + // use same adjustments as in ->draw, see there + g.x += g.xOff ? cwidth - g.xOff >> 1 : 0; + g.x += g.xOff ? 0 : cwidth; + int w = g.width - g.x; - careful = g.x > 0 || w > prop->width * wcw; + careful = g.x > 0 || w > cwidth; if (careful && !OVERLAP_OK (w, wcw, prop)) return false; @@ -1408,19 +1448,19 @@ int cwidth = term->fwidth; FcChar32 chr = *text++; len--; - // handle non-bmp chars when text_t is 16 bit - #if ENABLE_COMBINING && !UNICODE_3 - if (ecb_expect_false (IS_COMPOSE (chr))) - if (compose_char *cc = rxvt_composite [chr]) - if (cc->c2 == NOCHAR) - chr = cc->c1; - #endif - while (len && *text == NOCHAR) text++, len--, cwidth += term->fwidth; if (chr != ' ') // skip spaces { + // handle non-bmp chars when text_t is 16 bit + #if ENABLE_COMBINING && !UNICODE_3 + if (ecb_expect_false (IS_COMPOSE (chr))) + if (compose_char *cc = rxvt_composite [chr]) + if (cc->c2 == NOCHAR) + chr = cc->c1; + #endif + #if 0 FT_UInt glyphs [decltype (exp)::max_size]; @@ -1435,9 +1475,23 @@ } #endif - FT_UInt glyph = XftCharIndex (disp, f, chr); - XGlyphInfo extents; - XftGlyphExtents (disp, f, &glyph, 1, &extents); + FT_UInt glyph; + int xOff; + + #if XFT_CHAR_CACHE + if (ecb_expect_true (IN_RANGE_INC (chr, char_cache_min, char_cache_max))) + { + glyph = glyph_cache [chr - char_cache_min]; + xOff = xoff_cache [chr - char_cache_min]; + } + else + #endif + { + glyph = XftCharIndex (disp, f, chr); + XGlyphInfo extents; + XftGlyphExtents (disp, f, &glyph, 1, &extents); + xOff = extents.xOff; + } ep->glyph = glyph; ep->x = x_; @@ -1445,7 +1499,7 @@ // the xft font cell might differ from the terminal font cell, // in which case we use the average between the two. - ep->x += cwidth - extents.xOff >> 1; + ep->x += xOff ? cwidth - xOff >> 1 : 0; // xft/freetype represent combining characters as characters with zero // width rendered over the previous character with some fonts, while @@ -1454,7 +1508,7 @@ // we handle the first two cases by keying off on xOff being 0 // for zero-width chars. normally, we would add extents.xOff // of the base character here, but we don't have that, so we use cwidth. - ep->x += extents.xOff ? 0 : cwidth; + ep->x += xOff ? 0 : cwidth; ++ep; }