# st

Unnamed repository; edit this file 'description' to name the repository.

| Log | 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;
     	}