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:
st.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;
}