--- rxvt-unicode/src/rxvtfont.C 2020/01/20 09:35:17 1.197 +++ rxvt-unicode/src/rxvtfont.C 2021/06/17 11:45:19 1.204 @@ -214,7 +214,7 @@ ///////////////////////////////////////////////////////////////////////////// rxvt_font::rxvt_font () -: name(0), width(rxvt_fontprop::unset), height(rxvt_fontprop::unset) +: name(0), width(rxvt_fontprop::unset), height(rxvt_fontprop::unset), can_compose(false) { } @@ -264,7 +264,8 @@ ///////////////////////////////////////////////////////////////////////////// -struct rxvt_font_default : rxvt_font { +struct rxvt_font_default : rxvt_font +{ struct rxvt_fontset *fs; rxvt_font_default (rxvt_fontset *fs) @@ -314,8 +315,8 @@ return true; #endif - if (IS_COMPOSE (unicode)) - return true; + // we do not check for IS_COMPOSE here, as this would + // rob other fonts from taking over. switch (unicode) { @@ -346,15 +347,15 @@ while (len) { -#if ENABLE_COMBINING - compose_char *cc; -#endif const text_t *tp = text; text_t t = *tp; while (++text, --len && *text == NOCHAR) ; +#if ENABLE_COMBINING + compose_char *cc; +#endif int width = text - tp; int fwidth = term->fwidth * width; @@ -447,6 +448,28 @@ { min_it (width, 2); // we only support wcwidth up to 2 + #if NOT_YET + vector chrs; + chrs.reserve (rxvt_composite.expand (t)); + rxvt_composite.expand (t, &chrs[0]); + + while (!chrs.empty ()) + { + rxvt_font *f1 = fs->find_font_idx (chrs[0]) + + int i = 0; + while (i < chrs.size () - 1 + && f1->can_combine + && f1->has-char (chrs[i + 1], careful) + && !careful + ++i; + + (*fs)[f1]->draw (d, x, y, &chrs[0], width, fg, bg); + chrs.erase (&chrs[0], &chrs[i]); + } + #endif + + #if 1 text_t chrs[2]; chrs [1] = NOCHAR; @@ -466,6 +489,7 @@ f2->draw (d, x, y, chrs, width, fg, Color_none); } + #endif } #endif else @@ -476,6 +500,15 @@ case NOCHAR: break; + /* + * If the base font does not support variation selectors, treat them as ZWC. + * a point could be made to do this for all wcwidth == 0 characters, but I + * decided against that until more data is available. + */ + case 0xfe00: case 0xfe01: case 0xfe02: case 0xfe03: case 0xfe04: case 0xfe05: case 0xfe06: case 0xfe07: + case 0xfe08: case 0xfe09: case 0xfe0a: case 0xfe0b: case 0xfe0c: case 0xfe0d: case 0xfe0e: case 0xfe0f: + break; + default: XDrawRectangle (disp, d, gc, x + 2, y + 2, fwidth - 4, term->fheight - 4); @@ -485,7 +518,8 @@ } } -struct rxvt_font_overflow : rxvt_font { +struct rxvt_font_overflow : rxvt_font +{ struct rxvt_fontset *fs; rxvt_font_overflow (rxvt_fontset *fs) @@ -541,7 +575,8 @@ ///////////////////////////////////////////////////////////////////////////// -struct rxvt_font_x11 : rxvt_font { +struct rxvt_font_x11 : rxvt_font +{ rxvt_font_x11 () { f = 0; } void clear (); @@ -1126,8 +1161,13 @@ #if XFT -struct rxvt_font_xft : rxvt_font { - rxvt_font_xft () { f = 0; } +struct rxvt_font_xft : rxvt_font +{ + rxvt_font_xft () + { + can_compose = true; + f = 0; + } void clear (); @@ -1279,12 +1319,8 @@ if (!width) { - rxvt_warn ("unable to calculate font width for '%s', ignoring.\n", name); - - XftFontClose (disp, f); - f = 0; - - success = false; + rxvt_warn ("unable to calculate font width for '%s', using max_advance_width.\n", name); + width = f->max_advance_width; break; } @@ -1329,9 +1365,21 @@ { careful = false; +#if ENABLE_COMBINING && !UNICODE_3 + if (ecb_expect_false (IS_COMPOSE (unicode))) + if (compose_char *cc = rxvt_composite[unicode]) + if (cc->c2 == NOCHAR) + unicode = cc->c1; +#endif + if (!XftCharExists (term->dpy, f, unicode)) return false; + // some fonts claim they can render private use chars and then + // render them as boxes. + if (ecb_expect_false (IS_COMPOSE (unicode))) + return false; + if (!prop || prop->width == rxvt_fontprop::unset) return true; @@ -1385,6 +1433,12 @@ int cwidth = term->fwidth; FcChar32 fc = *text++; len--; +#if ENABLE_COMBINING && !UNICODE_3 + if (ecb_expect_false (IS_COMPOSE (fc))) + if (compose_char *cc = rxvt_composite[fc]) // should always be true, but better be safe than sorry + fc = cc->c1; // c2 must be NOCHAR, as has_char handles it that way +#endif + while (len && *text == NOCHAR) text++, len--, cwidth += term->fwidth; @@ -1679,15 +1733,16 @@ int rxvt_fontset::find_font_idx (unicode_t unicode) { - if (unicode >= 1<<20) + // this limits fmap size. it has to accomodate COMPOSE_HI when UNICODE_3 + if (unicode > 0x1fffff) return 0; unicode_t hi = unicode >> 8; - if (hi < fmap.size () - && fmap[hi] - && (*fmap[hi])[unicode & 0xff] != 0xff) - return (*fmap[hi])[unicode & 0xff]; + if (hi < fmap.size ()) + if (pagemap *pm = fmap[hi]) + if ((*pm)[unicode & 0xff] != 0xff) + return (*pm)[unicode & 0xff]; unsigned int i; @@ -1721,6 +1776,11 @@ next_font: if (i == fonts.size () - 1) { + // compose characters are handled by the default font, unless another font takes over + // we do not go via the fallback list for speed reasons. + if (IS_COMPOSE (unicode)) + return 0; + if (fallback->name) { // search through the fallback list