diff options
| -rw-r--r-- | x.c | 177 | 
1 files changed, 144 insertions, 33 deletions
@@ -19,6 +19,7 @@ char *argv0;  #include "arg.h"  #include "st.h"  #include "win.h" +#include "hb.h"  /* types used in config.h */  typedef struct { @@ -81,6 +82,7 @@ typedef XftGlyphFontSpec GlyphFontSpec;  typedef struct {  	int tw, th; /* tty width and height */  	int w, h; /* window width and height */ +	int hborderpx, vborderpx;  	int ch; /* char height */  	int cw; /* char width  */  	int mode; /* window state/mode flags */ @@ -157,6 +159,8 @@ static void xhints(void);  static int xloadcolor(int, const char *, Color *);  static int xloadfont(Font *, FcPattern *);  static void xloadfonts(const char *, double); +static int xloadsparefont(FcPattern *, int); +static void xloadsparefonts(void);  static void xunloadfont(Font *);  static void xunloadfonts(void);  static void xsetenv(void); @@ -306,6 +310,7 @@ zoomabs(const Arg *arg)  {  	xunloadfonts();  	xloadfonts(usedfont, arg->f); +	xloadsparefonts();  	cresize(0, 0);  	redraw();  	xhints(); @@ -331,7 +336,7 @@ ttysend(const Arg *arg)  int  evcol(XEvent *e)  { -	int x = e->xbutton.x - borderpx; +	int x = e->xbutton.x - win.hborderpx;  	LIMIT(x, 0, win.tw - 1);  	return x / win.cw;  } @@ -339,7 +344,7 @@ evcol(XEvent *e)  int  evrow(XEvent *e)  { -	int y = e->xbutton.y - borderpx; +	int y = e->xbutton.y - win.vborderpx;  	LIMIT(y, 0, win.th - 1);  	return y / win.ch;  } @@ -723,6 +728,9 @@ cresize(int width, int height)  	col = MAX(1, col);  	row = MAX(1, row); +	win.hborderpx = (win.w - col * win.cw) / 2; +	win.vborderpx = (win.h - row * win.ch) / 2; +  	tresize(col, row);  	xresize(col, row);  	ttyresize(win.tw, win.th); @@ -840,8 +848,8 @@ xhints(void)  	sizeh->flags = PSize | PResizeInc | PBaseSize | PMinSize;  	sizeh->height = win.h;  	sizeh->width = win.w; -	sizeh->height_inc = win.ch; -	sizeh->width_inc = win.cw; +	sizeh->height_inc = 1; +	sizeh->width_inc = 1;  	sizeh->base_height = 2 * borderpx;  	sizeh->base_width = 2 * borderpx;  	sizeh->min_height = win.ch + 2 * borderpx; @@ -1021,6 +1029,101 @@ xloadfonts(const char *fontstr, double fontsize)  	FcPatternDestroy(pattern);  } +int +xloadsparefont(FcPattern *pattern, int flags) +{ +	FcPattern *match; +	FcResult result; +	 +	match = FcFontMatch(NULL, pattern, &result); +	if (!match) { +		return 1; +	} + +	if (!(frc[frclen].font = XftFontOpenPattern(xw.dpy, match))) { +		FcPatternDestroy(match); +		return 1; +	} + +	frc[frclen].flags = flags; +	/* Believe U+0000 glyph will present in each default font */ +	frc[frclen].unicodep = 0; +	frclen++; + +	return 0; +} + +void +xloadsparefonts(void) +{ +	FcPattern *pattern; +	double sizeshift, fontval; +	int fc; +	char **fp; + +	if (frclen != 0) +		die("can't embed spare fonts. cache isn't empty"); + +	/* Calculate count of spare fonts */ +	fc = sizeof(font2) / sizeof(*font2); +	if (fc == 0) +		return; + +	/* Allocate memory for cache entries. */ +	if (frccap < 4 * fc) { +		frccap += 4 * fc - frccap; +		frc = xrealloc(frc, frccap * sizeof(Fontcache)); +	} + +	for (fp = font2; fp - font2 < fc; ++fp) { +	 +		if (**fp == '-') +			pattern = XftXlfdParse(*fp, False, False); +		else +			pattern = FcNameParse((FcChar8 *)*fp); +	 +		if (!pattern) +			die("can't open spare font %s\n", *fp); +	   		 +		if (defaultfontsize > 0) { +			sizeshift = usedfontsize - defaultfontsize; +			if (sizeshift != 0 && +					FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontval) == +					FcResultMatch) {	 +				fontval += sizeshift; +				FcPatternDel(pattern, FC_PIXEL_SIZE); +				FcPatternDel(pattern, FC_SIZE); +				FcPatternAddDouble(pattern, FC_PIXEL_SIZE, fontval); +			} +		} +	 +		FcPatternAddBool(pattern, FC_SCALABLE, 1); +	 +		FcConfigSubstitute(NULL, pattern, FcMatchPattern); +		XftDefaultSubstitute(xw.dpy, xw.scr, pattern); +	 +		if (xloadsparefont(pattern, FRC_NORMAL)) +			die("can't open spare font %s\n", *fp); +	 +		FcPatternDel(pattern, FC_SLANT); +		FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); +		if (xloadsparefont(pattern, FRC_ITALIC)) +			die("can't open spare font %s\n", *fp); +			 +		FcPatternDel(pattern, FC_WEIGHT); +		FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); +		if (xloadsparefont(pattern, FRC_ITALICBOLD)) +			die("can't open spare font %s\n", *fp); +	 +		FcPatternDel(pattern, FC_SLANT); +		FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN); +		if (xloadsparefont(pattern, FRC_BOLD)) +			die("can't open spare font %s\n", *fp); +	 +		FcPatternDestroy(pattern); +	} +} +  void  xunloadfont(Font *f)  { @@ -1033,6 +1136,9 @@ xunloadfont(Font *f)  void  xunloadfonts(void)  { +	/* Clear Harfbuzz font cache. */ +	hbunloadfonts(); +  	/* Free the loaded fonts in the font cache.  */  	while (frclen > 0)  		XftFontClose(xw.dpy, frc[--frclen].font); @@ -1118,13 +1224,16 @@ xinit(int cols, int rows)  	usedfont = (opt_font == NULL)? font : opt_font;  	xloadfonts(usedfont, 0); +	/* spare fonts */ +	xloadsparefonts(); +  	/* colors */  	xw.cmap = XDefaultColormap(xw.dpy, xw.scr);  	xloadcols();  	/* adjust fixed window geometry */ -	win.w = 2 * borderpx + cols * win.cw; -	win.h = 2 * borderpx + rows * win.ch; +	win.w = 2 * win.hborderpx + 2 * borderpx + cols * win.cw; +	win.h = 2 * win.vborderpx + 2 * borderpx + rows * win.ch;  	if (xw.gm & XNegative)  		xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2;  	if (xw.gm & YNegative) @@ -1213,7 +1322,7 @@ xinit(int cols, int rows)  int  xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y)  { -	float winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, xp, yp; +	float winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch, xp, yp;  	ushort mode, prevmode = USHRT_MAX;  	Font *font = &dc.font;  	int frcflags = FRC_NORMAL; @@ -1232,7 +1341,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x  		mode = glyphs[i].mode;  		/* Skip dummy wide-character spacing. */ -		if (mode == ATTR_WDUMMY) +		if (mode & ATTR_WDUMMY)  			continue;  		/* Determine font for glyph if different from previous glyph. */ @@ -1339,6 +1448,9 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x  		numspecs++;  	} +	/* Harfbuzz transformation for ligatures. */ +	hbtransform(specs, glyphs, len, x, y); +  	return numspecs;  } @@ -1346,7 +1458,7 @@ void  xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y)  {  	int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1); -	int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, +	int winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch,  	    width = charlen * win.cw;  	Color *fg, *bg, *temp, revfg, revbg, truefg, truebg;  	XRenderColor colfg, colbg; @@ -1383,10 +1495,6 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i  		bg = &dc.col[base.bg];  	} -	/* Change basic system colors [0-7] to bright system colors [8-15] */ -	if ((base.mode & ATTR_BOLD_FAINT) == ATTR_BOLD && BETWEEN(base.fg, 0, 7)) -		fg = &dc.col[base.fg + 8]; -  	if (IS_SET(MODE_REVERSE)) {  		if (fg == &dc.col[defaultfg]) {  			fg = &dc.col[defaultbg]; @@ -1436,17 +1544,17 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i  	/* Intelligent cleaning up of the borders. */  	if (x == 0) { -		xclear(0, (y == 0)? 0 : winy, borderpx, +		xclear(0, (y == 0)? 0 : winy, win.vborderpx,  			winy + win.ch + -			((winy + win.ch >= borderpx + win.th)? win.h : 0)); +			((winy + win.ch >= win.vborderpx + win.th)? win.h : 0));  	} -	if (winx + width >= borderpx + win.tw) { +	if (winx + width >= win.hborderpx + win.tw) {  		xclear(winx + width, (y == 0)? 0 : winy, win.w, -			((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch))); +			((winy + win.ch >= win.vborderpx + win.th)? win.h : (winy + win.ch)));  	}  	if (y == 0) -		xclear(winx, 0, winx + width, borderpx); -	if (winy + win.ch >= borderpx + win.th) +		xclear(winx, 0, winx + width, win.vborderpx); +	if (winy + win.ch >= win.vborderpx + win.th)  		xclear(winx, winy + win.ch, winx + width, win.h);  	/* Clean up the region we want to draw to. */ @@ -1488,14 +1596,17 @@ xdrawglyph(Glyph g, int x, int y)  }  void -xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) +xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line line, int len)  {  	Color drawcol;  	/* remove the old cursor */  	if (selected(ox, oy))  		og.mode ^= ATTR_REVERSE; -	xdrawglyph(og, ox, oy); + +	/* Redraw the line where cursor was previously. +	 * It will restore the ligatures broken by the cursor. */ +	xdrawline(line, 0, oy, len);  	if (IS_SET(MODE_HIDE))  		return; @@ -1540,35 +1651,35 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og)  		case 3: /* Blinking Underline */  		case 4: /* Steady Underline */  			XftDrawRect(xw.draw, &drawcol, -					borderpx + cx * win.cw, -					borderpx + (cy + 1) * win.ch - \ +					win.hborderpx + cx * win.cw, +					win.vborderpx + (cy + 1) * win.ch - \  						cursorthickness,  					win.cw, cursorthickness);  			break;  		case 5: /* Blinking bar */  		case 6: /* Steady bar */  			XftDrawRect(xw.draw, &drawcol, -					borderpx + cx * win.cw, -					borderpx + cy * win.ch, +					win.hborderpx + cx * win.cw, +					win.vborderpx + cy * win.ch,  					cursorthickness, win.ch);  			break;  		}  	} else {  		XftDrawRect(xw.draw, &drawcol, -				borderpx + cx * win.cw, -				borderpx + cy * win.ch, +				win.hborderpx + cx * win.cw, +				win.vborderpx + cy * win.ch,  				win.cw - 1, 1);  		XftDrawRect(xw.draw, &drawcol, -				borderpx + cx * win.cw, -				borderpx + cy * win.ch, +				win.hborderpx + cx * win.cw, +				win.vborderpx + cy * win.ch,  				1, win.ch - 1);  		XftDrawRect(xw.draw, &drawcol, -				borderpx + (cx + 1) * win.cw - 1, -				borderpx + cy * win.ch, +				win.hborderpx + (cx + 1) * win.cw - 1, +				win.vborderpx + cy * win.ch,  				1, win.ch - 1);  		XftDrawRect(xw.draw, &drawcol, -				borderpx + cx * win.cw, -				borderpx + (cy + 1) * win.ch - 1, +				win.hborderpx + cx * win.cw, +				win.vborderpx + (cy + 1) * win.ch - 1,  				win.cw, 1);  	}  }  | 
