From addc84834506e24387c1fb70b5d33b3f2ba55b66 Mon Sep 17 00:00:00 2001 From: Christoph Lohmann <20h@r-36.net> Date: Sat, 29 Dec 2012 15:03:03 +0100 Subject: Speeding up the drawing, then all characters are known. --- st.c | 176 ++++++++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 99 insertions(+), 77 deletions(-) diff --git a/st.c b/st.c index a440959..cc8a22a 100644 --- a/st.c +++ b/st.c @@ -437,7 +437,7 @@ typedef struct { */ static Fontcache frc[256]; -static int frccur = 0, frclen = 0; +static int frccur = -1, frclen = 0; ssize_t xwrite(int fd, char *s, size_t len) { @@ -2410,7 +2410,7 @@ xunloadfonts(void) ip = LEN(frc) - 1; XftFontClose(xw.dpy, frc[ip].font); } - frccur = 0; + frccur = -1; frclen = 0; XftFontClose(xw.dpy, dc.font.match); @@ -2532,11 +2532,12 @@ xinit(void) { void xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { int winx = borderpx + x * xw.cw, winy = borderpx + y * xw.ch, - width = charlen * xw.cw, u8clen, xp, i, frp, frcflags; + width = charlen * xw.cw, xp, i; + int frp, frcflags; + int u8fl, u8fblen, u8cblen, doesexist; + char *u8c, *u8fs; long u8char; - char *u8c; Font *font = &dc.font; - XftFont *sfont; FcResult fcres; FcPattern *fcpattern, *fontpattern; FcFontSet *fcsets[] = { NULL }; @@ -2608,11 +2609,6 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { bg = temp; } - /* Width of the whole string that should be printed. */ - XftTextExtentsUtf8(xw.dpy, font->match, (FcChar8 *)s, bytelen, - &extents); - width = extents.xOff; - /* Intelligent cleaning up of the borders. */ if(x == 0) { xclear(0, (y == 0)? 0 : winy, borderpx, @@ -2630,85 +2626,111 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { /* Clean up the region we want to draw to. */ XftDrawRect(xw.draw, bg, winx, winy, width, xw.ch); - /* - * Step through all UTF-8 characters one by one and search in the font - * cache ring buffer, whether there was some font found to display the - * unicode value of that UTF-8 character. - */ fcsets[0] = font->set; - for (xp = winx; bytelen > 0; ) { - u8c = s; - u8clen = utf8decode(s, &u8char); - s += u8clen; - bytelen -= u8clen; - - sfont = font->match; + for (xp = winx; bytelen > 0;) { /* - * Only check the font cache or load new fonts, if the - * characters is not represented in main font. + * Search for the range in the to be printed string of glyphs + * that are in the main font. Then print that range. If + * some glyph is found that is not in the font, do the + * fallback dance. */ - if (!XftCharExists(xw.dpy, font->match, u8char)) { - frp = frccur; - /* Search the font cache. */ - for (i = 0; i < frclen; i++, frp--) { - if (frp <= 0) - frp = LEN(frc) - 1; + u8fs = s; + u8fblen = 0; + u8fl = 0; + for (;;) { + u8c = s; + u8cblen = utf8decode(s, &u8char); + s += u8cblen; + bytelen -= u8cblen; + + doesexist = XftCharIndex(xw.dpy, font->match, u8char); + if (!doesexist || bytelen <= 0) { + if (bytelen <= 0) { + if (doesexist) { + u8fl++; + u8fblen += u8cblen; + } + } - if (frc[frp].c == u8char - && frc[frp].flags == frcflags) { - break; + if (u8fl > 0) { + XftDrawStringUtf8(xw.draw, fg, + font->match, xp, + winy + font->ascent, + (FcChar8 *)u8fs, + u8fblen); + xp += font->width * u8fl; } + break; } - if (i >= frclen) { - /* - * Nothing was found in the cache. Now use - * some dozen of Fontconfig calls to get the - * font for one single character. - */ - fcpattern = FcPatternDuplicate(font->pattern); - fccharset = FcCharSetCreate(); - - FcCharSetAddChar(fccharset, u8char); - FcPatternAddCharSet(fcpattern, FC_CHARSET, - fccharset); - FcPatternAddBool(fcpattern, FC_SCALABLE, - FcTrue); - - FcConfigSubstitute(0, fcpattern, - FcMatchPattern); - FcDefaultSubstitute(fcpattern); - - fontpattern = FcFontSetMatch(0, fcsets, - FcTrue, fcpattern, &fcres); - - frccur++; - frclen++; - if (frccur >= LEN(frc)) - frccur = 0; - if (frclen >= LEN(frc)) { - frclen = LEN(frc); - XftFontClose(xw.dpy, frc[frccur].font); - } - /* - * Overwrite or create the new cache entry - * entry. - */ - frc[frccur].font = XftFontOpenPattern(xw.dpy, - fontpattern); - frc[frccur].c = u8char; - frc[frccur].flags = frcflags; + u8fl++; + u8fblen += u8cblen; + } + if (doesexist) + break; - FcPatternDestroy(fcpattern); - FcCharSetDestroy(fccharset); + frp = frccur; + /* Search the font cache. */ + for (i = 0; i < frclen; i++, frp--) { + if (frp <= 0) + frp = LEN(frc) - 1; - frp = frccur; + if (frc[frp].c == u8char + && frc[frp].flags == frcflags) { + break; } - sfont = frc[frp].font; } - XftDrawStringUtf8(xw.draw, fg, sfont, xp, winy + sfont->ascent, - (FcChar8 *)u8c, u8clen); + /* Nothing was found. */ + if (i >= frclen) { + /* + * Nothing was found in the cache. Now use + * some dozen of Fontconfig calls to get the + * font for one single character. + */ + fcpattern = FcPatternDuplicate(font->pattern); + fccharset = FcCharSetCreate(); + + FcCharSetAddChar(fccharset, u8char); + FcPatternAddCharSet(fcpattern, FC_CHARSET, + fccharset); + FcPatternAddBool(fcpattern, FC_SCALABLE, + FcTrue); + + FcConfigSubstitute(0, fcpattern, + FcMatchPattern); + FcDefaultSubstitute(fcpattern); + + fontpattern = FcFontSetMatch(0, fcsets, + FcTrue, fcpattern, &fcres); + + /* + * Overwrite or create the new cache entry + * entry. + */ + frccur++; + frclen++; + if (frccur >= LEN(frc)) + frccur = 0; + if (frclen > LEN(frc)) { + frclen = LEN(frc); + XftFontClose(xw.dpy, frc[frccur].font); + } + + frc[frccur].font = XftFontOpenPattern(xw.dpy, + fontpattern); + frc[frccur].c = u8char; + frc[frccur].flags = frcflags; + + FcPatternDestroy(fcpattern); + FcCharSetDestroy(fccharset); + + frp = frccur; + } + + XftDrawStringUtf8(xw.draw, fg, frc[frp].font, + xp, winy + frc[frp].font->ascent, + (FcChar8 *)u8c, u8cblen); xp += font->width; } -- cgit v1.2.3-13-gbd6f