aboutsummaryrefslogtreecommitdiff
path: root/st.c
diff options
context:
space:
mode:
authorEon S. Jeon <esjeon@lavabit.com>2013-07-19 01:07:02 -0400
committerRoberto E. Vargas Caballero <k0ga@shike2.com>2013-07-19 08:38:10 +0200
commit33ad83d49213749f4fcec850327f57a33ca8b921 (patch)
tree264341fa0a2e832b95af7d92753e30c1faf894da /st.c
parent40e4d76d227d9c517054036f546acd49431bca42 (diff)
downloadst-33ad83d49213749f4fcec850327f57a33ca8b921.tar.gz
st-33ad83d49213749f4fcec850327f57a33ca8b921.zip
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.
Diffstat (limited to 'st.c')
-rw-r--r--st.c63
1 files changed, 22 insertions, 41 deletions
diff --git a/st.c b/st.c
index 289ecb8..947373f 100644
--- a/st.c
+++ b/st.c
@@ -462,17 +462,12 @@ enum {
462 462
463typedef struct { 463typedef struct {
464 XftFont *font; 464 XftFont *font;
465 long c;
466 int flags; 465 int flags;
467} Fontcache; 466} Fontcache;
468 467
469/* 468/* Fontcache is an array now. A new font will be appended to the array. */
470 * Fontcache is a ring buffer, with frccur as current position and frclen as 469static Fontcache frc[16];
471 * the current length of used elements. 470static int frclen = 0;
472 */
473
474static Fontcache frc[1024];
475static int frccur = -1, frclen = 0;
476 471
477ssize_t 472ssize_t
478xwrite(int fd, char *s, size_t len) { 473xwrite(int fd, char *s, size_t len) {
@@ -2781,18 +2776,12 @@ xunloadfont(Font *f) {
2781 2776
2782void 2777void
2783xunloadfonts(void) { 2778xunloadfonts(void) {
2784 int i, ip; 2779 int i;
2785 2780
2786 /* 2781 /* Free the loaded fonts in the font cache. */
2787 * Free the loaded fonts in the font cache. This is done backwards 2782 for(i = 0; i < frclen; i++) {
2788 * from the frccur. 2783 XftFontClose(xw.dpy, frc[i].font);
2789 */
2790 for(i = 0, ip = frccur; i < frclen; i++, ip--) {
2791 if(ip < 0)
2792 ip = LEN(frc) - 1;
2793 XftFontClose(xw.dpy, frc[ip].font);
2794 } 2784 }
2795 frccur = -1;
2796 frclen = 0; 2785 frclen = 0;
2797 2786
2798 xunloadfont(&dc.font); 2787 xunloadfont(&dc.font);
@@ -2918,7 +2907,7 @@ void
2918xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { 2907xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) {
2919 int winx = borderpx + x * xw.cw, winy = borderpx + y * xw.ch, 2908 int winx = borderpx + x * xw.cw, winy = borderpx + y * xw.ch,
2920 width = charlen * xw.cw, xp, i; 2909 width = charlen * xw.cw, xp, i;
2921 int frp, frcflags; 2910 int frcflags;
2922 int u8fl, u8fblen, u8cblen, doesexist; 2911 int u8fl, u8fblen, u8cblen, doesexist;
2923 char *u8c, *u8fs; 2912 char *u8c, *u8fs;
2924 long u8char; 2913 long u8char;
@@ -3044,7 +3033,7 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) {
3044 s += u8cblen; 3033 s += u8cblen;
3045 bytelen -= u8cblen; 3034 bytelen -= u8cblen;
3046 3035
3047 doesexist = XftCharIndex(xw.dpy, font->match, u8char); 3036 doesexist = XftCharExists(xw.dpy, font->match, u8char);
3048 if(!doesexist || bytelen <= 0) { 3037 if(!doesexist || bytelen <= 0) {
3049 if(bytelen <= 0) { 3038 if(bytelen <= 0) {
3050 if(doesexist) { 3039 if(doesexist) {
@@ -3071,14 +3060,10 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) {
3071 if(doesexist) 3060 if(doesexist)
3072 break; 3061 break;
3073 3062
3074 frp = frccur;
3075 /* Search the font cache. */ 3063 /* Search the font cache. */
3076 for(i = 0; i < frclen; i++, frp--) { 3064 for(i = 0; i < frclen; i++) {
3077 if(frp <= 0) 3065 if(XftCharExists(xw.dpy, frc[i].font, u8char)
3078 frp = LEN(frc) - 1; 3066 && frc[i].flags == frcflags) {
3079
3080 if(frc[frp].c == u8char
3081 && frc[frp].flags == frcflags) {
3082 break; 3067 break;
3083 } 3068 }
3084 } 3069 }
@@ -3113,28 +3098,24 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) {
3113 /* 3098 /*
3114 * Overwrite or create the new cache entry. 3099 * Overwrite or create the new cache entry.
3115 */ 3100 */
3116 frccur++; 3101 if(frclen >= LEN(frc)) {
3117 frclen++; 3102 frclen = LEN(frc) - 1;
3118 if(frccur >= LEN(frc)) 3103 XftFontClose(xw.dpy, frc[frclen].font);
3119 frccur = 0;
3120 if(frclen > LEN(frc)) {
3121 frclen = LEN(frc);
3122 XftFontClose(xw.dpy, frc[frccur].font);
3123 } 3104 }
3124 3105
3125 frc[frccur].font = XftFontOpenPattern(xw.dpy, 3106 frc[frclen].font = XftFontOpenPattern(xw.dpy,
3126 fontpattern); 3107 fontpattern);
3127 frc[frccur].c = u8char; 3108 frc[frclen].flags = frcflags;
3128 frc[frccur].flags = frcflags; 3109
3110 i = frclen;
3111 frclen++;
3129 3112
3130 FcPatternDestroy(fcpattern); 3113 FcPatternDestroy(fcpattern);
3131 FcCharSetDestroy(fccharset); 3114 FcCharSetDestroy(fccharset);
3132
3133 frp = frccur;
3134 } 3115 }
3135 3116
3136 XftDrawStringUtf8(xw.draw, fg, frc[frp].font, 3117 XftDrawStringUtf8(xw.draw, fg, frc[i].font,
3137 xp, winy + frc[frp].font->ascent, 3118 xp, winy + frc[i].font->ascent,
3138 (FcChar8 *)u8c, u8cblen); 3119 (FcChar8 *)u8c, u8cblen);
3139 3120
3140 xp += font->width; 3121 xp += font->width;