Fix wide glyphs truncation
This commit is contained in:
		
							
								
								
									
										6
									
								
								st.h
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								st.h
									
									
									
									
									
								
							@@ -37,6 +37,12 @@ enum glyph_attribute {
 | 
			
		||||
	ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum drawing_mode {
 | 
			
		||||
	DRAW_NONE = 0,
 | 
			
		||||
	DRAW_BG   = 1 << 0,
 | 
			
		||||
	DRAW_FG   = 1 << 1,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum selection_mode {
 | 
			
		||||
	SEL_IDLE = 0,
 | 
			
		||||
	SEL_EMPTY = 1,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										121
									
								
								x.c
									
									
									
									
									
								
							
							
						
						
									
										121
									
								
								x.c
									
									
									
									
									
								
							@@ -152,7 +152,7 @@ typedef struct {
 | 
			
		||||
 | 
			
		||||
static inline ushort sixd_to_16bit(int);
 | 
			
		||||
static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int);
 | 
			
		||||
static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int);
 | 
			
		||||
static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int, int);
 | 
			
		||||
static void xdrawglyph(Glyph, int, int);
 | 
			
		||||
static void xclear(int, int, int, int);
 | 
			
		||||
static int xgeommasktogravity(int);
 | 
			
		||||
@@ -1445,7 +1445,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y)
 | 
			
		||||
xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y, int dmode)
 | 
			
		||||
{
 | 
			
		||||
	int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1);
 | 
			
		||||
	int winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch,
 | 
			
		||||
@@ -1531,40 +1531,44 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
 | 
			
		||||
	if (base.mode & ATTR_INVISIBLE)
 | 
			
		||||
		fg = bg;
 | 
			
		||||
 | 
			
		||||
	/* Intelligent cleaning up of the borders. */
 | 
			
		||||
	if (x == 0) {
 | 
			
		||||
		xclear(0, (y == 0)? 0 : winy, win.vborderpx,
 | 
			
		||||
			winy + win.ch +
 | 
			
		||||
			((winy + win.ch >= win.vborderpx + win.th)? win.h : 0));
 | 
			
		||||
	}
 | 
			
		||||
	if (winx + width >= win.hborderpx + win.tw) {
 | 
			
		||||
		xclear(winx + width, (y == 0)? 0 : winy, win.w,
 | 
			
		||||
			((winy + win.ch >= win.vborderpx + win.th)? win.h : (winy + win.ch)));
 | 
			
		||||
	}
 | 
			
		||||
	if (y == 0)
 | 
			
		||||
		xclear(winx, 0, winx + width, win.hborderpx);
 | 
			
		||||
	if (winy + win.ch >= win.vborderpx + win.th)
 | 
			
		||||
		xclear(winx, winy + win.ch, winx + width, win.h);
 | 
			
		||||
	if (dmode & DRAW_BG) {
 | 
			
		||||
		/* Intelligent cleaning up of the borders. */
 | 
			
		||||
		if (x == 0) {
 | 
			
		||||
			xclear(0, (y == 0)? 0 : winy, win.vborderpx,
 | 
			
		||||
					winy + win.ch +
 | 
			
		||||
					((winy + win.ch >= win.vborderpx + win.th)? win.h : 0));
 | 
			
		||||
		}
 | 
			
		||||
		if (winx + width >= win.hborderpx + win.tw) {
 | 
			
		||||
			xclear(winx + width, (y == 0)? 0 : winy, win.w,
 | 
			
		||||
					((winy + win.ch >= win.vborderpx + win.th)? win.h : (winy + win.ch)));
 | 
			
		||||
		}
 | 
			
		||||
		if (y == 0)
 | 
			
		||||
			xclear(winx, 0, winx + width, win.hborderpx);
 | 
			
		||||
		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. */
 | 
			
		||||
	XftDrawRect(xw.draw, bg, winx, winy, width, win.ch);
 | 
			
		||||
 | 
			
		||||
	if (base.mode & ATTR_BOXDRAW) {
 | 
			
		||||
		drawboxes(winx, winy, width / len, win.ch, fg, bg, specs, len);
 | 
			
		||||
	} else {
 | 
			
		||||
		/* Render the glyphs. */
 | 
			
		||||
		XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
 | 
			
		||||
		/* Fill the background */
 | 
			
		||||
		XftDrawRect(xw.draw, bg, winx, winy, width, win.ch);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Render underline and strikethrough. */
 | 
			
		||||
	if (base.mode & ATTR_UNDERLINE) {
 | 
			
		||||
		XftDrawRect(xw.draw, fg, winx, winy + win.cyo + dc.font.ascent + 1,
 | 
			
		||||
				width, 1);
 | 
			
		||||
	}
 | 
			
		||||
	if (dmode & DRAW_FG) {
 | 
			
		||||
		if (base.mode & ATTR_BOXDRAW) {
 | 
			
		||||
			drawboxes(winx, winy, width / len, win.ch, fg, bg, specs, len);
 | 
			
		||||
		} else {
 | 
			
		||||
			/* Render the glyphs. */
 | 
			
		||||
			XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	if (base.mode & ATTR_STRUCK) {
 | 
			
		||||
		XftDrawRect(xw.draw, fg, winx, winy + win.cyo + 2 * dc.font.ascent / 3,
 | 
			
		||||
				width, 1);
 | 
			
		||||
		/* Render underline and strikethrough. */
 | 
			
		||||
		if (base.mode & ATTR_UNDERLINE) {
 | 
			
		||||
			XftDrawRect(xw.draw, fg, winx, winy + win.cyo + dc.font.ascent + 1,
 | 
			
		||||
					width, 1);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (base.mode & ATTR_STRUCK) {
 | 
			
		||||
			XftDrawRect(xw.draw, fg, winx, winy + win.cyo + 2 * dc.font.ascent / 3,
 | 
			
		||||
					width, 1);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1575,7 +1579,7 @@ xdrawglyph(Glyph g, int x, int y)
 | 
			
		||||
	XftGlyphFontSpec spec;
 | 
			
		||||
 | 
			
		||||
	numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y);
 | 
			
		||||
	xdrawglyphfontspecs(&spec, g, numspecs, x, y);
 | 
			
		||||
	xdrawglyphfontspecs(&spec, g, numspecs, x, y, DRAW_BG | DRAW_FG);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -1694,32 +1698,39 @@ xstartdraw(void)
 | 
			
		||||
void
 | 
			
		||||
xdrawline(Line line, int x1, int y1, int x2)
 | 
			
		||||
{
 | 
			
		||||
	int i, x, ox, numspecs;
 | 
			
		||||
	int i, x, ox, numspecs, numspecs_cached;
 | 
			
		||||
	Glyph base, new;
 | 
			
		||||
	XftGlyphFontSpec *specs = xw.specbuf;
 | 
			
		||||
	XftGlyphFontSpec *specs;
 | 
			
		||||
 | 
			
		||||
	numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1);
 | 
			
		||||
	i = ox = 0;
 | 
			
		||||
	for (x = x1; x < x2 && i < numspecs; x++) {
 | 
			
		||||
		new = line[x];
 | 
			
		||||
		if (new.mode == ATTR_WDUMMY)
 | 
			
		||||
			continue;
 | 
			
		||||
		if (selected(x, y1))
 | 
			
		||||
			new.mode ^= ATTR_REVERSE;
 | 
			
		||||
		if (i > 0 && ATTRCMP(base, new)) {
 | 
			
		||||
			xdrawglyphfontspecs(specs, base, i, ox, y1);
 | 
			
		||||
			specs += i;
 | 
			
		||||
			numspecs -= i;
 | 
			
		||||
			i = 0;
 | 
			
		||||
	numspecs_cached = xmakeglyphfontspecs(xw.specbuf, &line[x1], x2 - x1, x1, y1);
 | 
			
		||||
 | 
			
		||||
	/* Draw line in 2 passes: background and foreground. This way wide glyphs
 | 
			
		||||
	   won't get truncated (#223) */
 | 
			
		||||
	for (int dmode = DRAW_BG; dmode <= DRAW_FG; dmode <<= 1) {
 | 
			
		||||
		specs = xw.specbuf;
 | 
			
		||||
		numspecs = numspecs_cached;
 | 
			
		||||
		i = ox = 0;
 | 
			
		||||
		for (x = x1; x < x2 && i < numspecs; x++) {
 | 
			
		||||
			new = line[x];
 | 
			
		||||
			if (new.mode == ATTR_WDUMMY)
 | 
			
		||||
				continue;
 | 
			
		||||
			if (selected(x, y1))
 | 
			
		||||
				new.mode ^= ATTR_REVERSE;
 | 
			
		||||
			if (i > 0 && ATTRCMP(base, new)) {
 | 
			
		||||
				xdrawglyphfontspecs(specs, base, i, ox, y1, dmode);
 | 
			
		||||
				specs += i;
 | 
			
		||||
				numspecs -= i;
 | 
			
		||||
				i = 0;
 | 
			
		||||
			}
 | 
			
		||||
			if (i == 0) {
 | 
			
		||||
				ox = x;
 | 
			
		||||
				base = new;
 | 
			
		||||
			}
 | 
			
		||||
			i++;
 | 
			
		||||
		}
 | 
			
		||||
		if (i == 0) {
 | 
			
		||||
			ox = x;
 | 
			
		||||
			base = new;
 | 
			
		||||
		}
 | 
			
		||||
		i++;
 | 
			
		||||
		if (i > 0)
 | 
			
		||||
			xdrawglyphfontspecs(specs, base, i, ox, y1, dmode);
 | 
			
		||||
	}
 | 
			
		||||
	if (i > 0)
 | 
			
		||||
		xdrawglyphfontspecs(specs, base, i, ox, y1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user