st

fork of suckless's simple terminal
Index Commits Files Refs README LICENSE
commit addc84834506e24387c1fb70b5d33b3f2ba55b66
parent 9c44229c626ea7351a7809540435f40cffb624bc
Author: Christoph Lohmann <20h@r-36.net>
Date:   Sat, 29 Dec 2012 15:03:03 +0100

Speeding up the drawing, then all characters are known.

Diffstat:
Mst.c | 176++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
1 file changed, 99 insertions(+), 77 deletions(-)
diff --git 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;
     }