Improved font caching
I made a patch that improves the performance of font caching mechanism. This is based on a funny behaviour of FontConfig: it was handling FcCharSet in a somewhat unexpected way. So, we are currently adding "a character" to a new FcCharSet, and then add it to a FcPattern. However, if we toss the FcPattern to FontConfig, it loads the entire language(charset) that contains the character we gave. That is, we don't always have to load a new font for each unknown character. Instead, we can reused cached fonts, and this significantly reduces the number of calls to extremely slow FontConfig matching functions. One more thing. I found that, in libXft, there's a function called XftCharExists. XftCharIndex internally calls this function, and does more stuffs if the character does exist. Since the returned index is never used in st, we should call XftCharExists instead of XftCharIndex. Please note that I already made this change in the patch.dev
parent
40e4d76d22
commit
33ad83d492
63
st.c
63
st.c
|
@ -462,17 +462,12 @@ enum {
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
XftFont *font;
|
XftFont *font;
|
||||||
long c;
|
|
||||||
int flags;
|
int flags;
|
||||||
} Fontcache;
|
} Fontcache;
|
||||||
|
|
||||||
/*
|
/* Fontcache is an array now. A new font will be appended to the array. */
|
||||||
* Fontcache is a ring buffer, with frccur as current position and frclen as
|
static Fontcache frc[16];
|
||||||
* the current length of used elements.
|
static int frclen = 0;
|
||||||
*/
|
|
||||||
|
|
||||||
static Fontcache frc[1024];
|
|
||||||
static int frccur = -1, frclen = 0;
|
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
xwrite(int fd, char *s, size_t len) {
|
xwrite(int fd, char *s, size_t len) {
|
||||||
|
@ -2781,18 +2776,12 @@ xunloadfont(Font *f) {
|
||||||
|
|
||||||
void
|
void
|
||||||
xunloadfonts(void) {
|
xunloadfonts(void) {
|
||||||
int i, ip;
|
int i;
|
||||||
|
|
||||||
/*
|
/* Free the loaded fonts in the font cache. */
|
||||||
* Free the loaded fonts in the font cache. This is done backwards
|
for(i = 0; i < frclen; i++) {
|
||||||
* from the frccur.
|
XftFontClose(xw.dpy, frc[i].font);
|
||||||
*/
|
|
||||||
for(i = 0, ip = frccur; i < frclen; i++, ip--) {
|
|
||||||
if(ip < 0)
|
|
||||||
ip = LEN(frc) - 1;
|
|
||||||
XftFontClose(xw.dpy, frc[ip].font);
|
|
||||||
}
|
}
|
||||||
frccur = -1;
|
|
||||||
frclen = 0;
|
frclen = 0;
|
||||||
|
|
||||||
xunloadfont(&dc.font);
|
xunloadfont(&dc.font);
|
||||||
|
@ -2918,7 +2907,7 @@ void
|
||||||
xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) {
|
xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) {
|
||||||
int winx = borderpx + x * xw.cw, winy = borderpx + y * xw.ch,
|
int winx = borderpx + x * xw.cw, winy = borderpx + y * xw.ch,
|
||||||
width = charlen * xw.cw, xp, i;
|
width = charlen * xw.cw, xp, i;
|
||||||
int frp, frcflags;
|
int frcflags;
|
||||||
int u8fl, u8fblen, u8cblen, doesexist;
|
int u8fl, u8fblen, u8cblen, doesexist;
|
||||||
char *u8c, *u8fs;
|
char *u8c, *u8fs;
|
||||||
long u8char;
|
long u8char;
|
||||||
|
@ -3044,7 +3033,7 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) {
|
||||||
s += u8cblen;
|
s += u8cblen;
|
||||||
bytelen -= u8cblen;
|
bytelen -= u8cblen;
|
||||||
|
|
||||||
doesexist = XftCharIndex(xw.dpy, font->match, u8char);
|
doesexist = XftCharExists(xw.dpy, font->match, u8char);
|
||||||
if(!doesexist || bytelen <= 0) {
|
if(!doesexist || bytelen <= 0) {
|
||||||
if(bytelen <= 0) {
|
if(bytelen <= 0) {
|
||||||
if(doesexist) {
|
if(doesexist) {
|
||||||
|
@ -3071,14 +3060,10 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) {
|
||||||
if(doesexist)
|
if(doesexist)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
frp = frccur;
|
|
||||||
/* Search the font cache. */
|
/* Search the font cache. */
|
||||||
for(i = 0; i < frclen; i++, frp--) {
|
for(i = 0; i < frclen; i++) {
|
||||||
if(frp <= 0)
|
if(XftCharExists(xw.dpy, frc[i].font, u8char)
|
||||||
frp = LEN(frc) - 1;
|
&& frc[i].flags == frcflags) {
|
||||||
|
|
||||||
if(frc[frp].c == u8char
|
|
||||||
&& frc[frp].flags == frcflags) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3113,28 +3098,24 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) {
|
||||||
/*
|
/*
|
||||||
* Overwrite or create the new cache entry.
|
* Overwrite or create the new cache entry.
|
||||||
*/
|
*/
|
||||||
frccur++;
|
if(frclen >= LEN(frc)) {
|
||||||
frclen++;
|
frclen = LEN(frc) - 1;
|
||||||
if(frccur >= LEN(frc))
|
XftFontClose(xw.dpy, frc[frclen].font);
|
||||||
frccur = 0;
|
|
||||||
if(frclen > LEN(frc)) {
|
|
||||||
frclen = LEN(frc);
|
|
||||||
XftFontClose(xw.dpy, frc[frccur].font);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
frc[frccur].font = XftFontOpenPattern(xw.dpy,
|
frc[frclen].font = XftFontOpenPattern(xw.dpy,
|
||||||
fontpattern);
|
fontpattern);
|
||||||
frc[frccur].c = u8char;
|
frc[frclen].flags = frcflags;
|
||||||
frc[frccur].flags = frcflags;
|
|
||||||
|
i = frclen;
|
||||||
|
frclen++;
|
||||||
|
|
||||||
FcPatternDestroy(fcpattern);
|
FcPatternDestroy(fcpattern);
|
||||||
FcCharSetDestroy(fccharset);
|
FcCharSetDestroy(fccharset);
|
||||||
|
|
||||||
frp = frccur;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
XftDrawStringUtf8(xw.draw, fg, frc[frp].font,
|
XftDrawStringUtf8(xw.draw, fg, frc[i].font,
|
||||||
xp, winy + frc[frp].font->ascent,
|
xp, winy + frc[i].font->ascent,
|
||||||
(FcChar8 *)u8c, u8cblen);
|
(FcChar8 *)u8c, u8cblen);
|
||||||
|
|
||||||
xp += font->width;
|
xp += font->width;
|
||||||
|
|
Loading…
Reference in New Issue