Procházet zdrojové kódy

Speeding up the drawing, then all characters are known.

Christoph Lohmann před 12 roky
rodič
revize
addc848345
1 změnil soubory, kde provedl 99 přidání a 77 odebrání
  1. 99 77
      st.c

+ 99 - 77
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;
 	}