sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

st-glyph-wide-support-boxdraw-20220411-ef05519.diff (6352B)


      1 From 9583955da47177c9557210f70baaaf9511ba106c Mon Sep 17 00:00:00 2001
      2 From: wael <40663@protonmail.com>
      3 Date: Mon, 11 Apr 2022 17:14:06 +0300
      4 Subject: [PATCH] boxdraw support for glyph wide support
      5 
      6 ---
      7  st.h |   6 +++
      8  x.c  | 139 ++++++++++++++++++++++++++++++-----------------------------
      9  2 files changed, 76 insertions(+), 69 deletions(-)
     10 
     11 diff --git a/st.h b/st.h
     12 index 07a7c66..3b8c97d 100644
     13 --- a/st.h
     14 +++ b/st.h
     15 @@ -37,6 +37,12 @@ enum glyph_attribute {
     16  	ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
     17  };
     18  
     19 +enum drawing_mode {
     20 +    DRAW_NONE = 0,
     21 +    DRAW_BG = 1 << 0,
     22 +    DRAW_FG = 1 << 1,
     23 +};
     24 +
     25  enum selection_mode {
     26  	SEL_IDLE = 0,
     27  	SEL_EMPTY = 1,
     28 diff --git a/x.c b/x.c
     29 index bf6bbf9..1311c0d 100644
     30 --- a/x.c
     31 +++ b/x.c
     32 @@ -142,7 +142,7 @@ typedef struct {
     33  
     34  static inline ushort sixd_to_16bit(int);
     35  static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int);
     36 -static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int);
     37 +static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int, int);
     38  static void xdrawglyph(Glyph, int, int);
     39  static void xclear(int, int, int, int);
     40  static int xgeommasktogravity(int);
     41 @@ -1379,7 +1379,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
     42  }
     43  
     44  void
     45 -xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y)
     46 +xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y, int dmode)
     47  {
     48  	int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1);
     49  	int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch,
     50 @@ -1470,51 +1470,45 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
     51  	if (base.mode & ATTR_INVISIBLE)
     52  		fg = bg;
     53  
     54 -	/* Intelligent cleaning up of the borders. */
     55 -	if (x == 0) {
     56 -		xclear(0, (y == 0)? 0 : winy, borderpx,
     57 -			winy + win.ch +
     58 -			((winy + win.ch >= borderpx + win.th)? win.h : 0));
     59 -	}
     60 -	if (winx + width >= borderpx + win.tw) {
     61 -		xclear(winx + width, (y == 0)? 0 : winy, win.w,
     62 -			((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch)));
     63 -	}
     64 -	if (y == 0)
     65 -		xclear(winx, 0, winx + width, borderpx);
     66 -	if (winy + win.ch >= borderpx + win.th)
     67 -		xclear(winx, winy + win.ch, winx + width, win.h);
     68 -
     69 -	/* Clean up the region we want to draw to. */
     70 -	XftDrawRect(xw.draw, bg, winx, winy, width, win.ch);
     71 -
     72 -	/* Set the clip region because Xft is sometimes dirty. */
     73 -	r.x = 0;
     74 -	r.y = 0;
     75 -	r.height = win.ch;
     76 -	r.width = width;
     77 -	XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1);
     78 -
     79 -	if (base.mode & ATTR_BOXDRAW) {
     80 -		drawboxes(winx, winy, width / len, win.ch, fg, bg, specs, len);
     81 -	} else {
     82 -		/* Render the glyphs. */
     83 -		XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
     84 -	}
     85 +    if (dmode & DRAW_BG) {
     86 +        /* Intelligent cleaning up of the borders. */
     87 +        if (x == 0) {
     88 +            xclear(0, (y == 0)? 0 : winy, borderpx,
     89 +                   winy + win.ch +
     90 +                   ((winy + win.ch >= borderpx + win.th)? win.h : 0));
     91 +        }
     92 +        if (winx + width >= borderpx + win.tw) {
     93 +            xclear(winx + width, (y == 0)? 0 : winy, win.w,
     94 +                   ((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch)));
     95 +        }
     96 +        if (y == 0)
     97 +            xclear(winx, 0, winx + width, borderpx);
     98 +        if (winy + win.ch >= borderpx + win.th)
     99 +            xclear(winx, winy + win.ch, winx + width, win.h);
    100 +        /* Fill the background */
    101 +        XftDrawRect(xw.draw, bg, winx, winy, width, win.ch);
    102 +    }
    103 +
    104 +
    105 +    if (dmode & DRAW_FG) {
    106 +		if (base.mode & ATTR_BOXDRAW) {
    107 +			drawboxes(winx, winy, width / len, win.ch, fg, bg, specs, len);
    108 +		} else {
    109 +			/* Render the glyphs. */
    110 +			XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
    111 +		}
    112  
    113 -	/* Render underline and strikethrough. */
    114 -	if (base.mode & ATTR_UNDERLINE) {
    115 -		XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent * chscale + 1,
    116 -				width, 1);
    117 -	}
    118 +        /* Render underline and strikethrough. */
    119 +        if (base.mode & ATTR_UNDERLINE) {
    120 +            XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1,
    121 +                        width, 1);
    122 +        }
    123  
    124 -	if (base.mode & ATTR_STRUCK) {
    125 -		XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent * chscale / 3,
    126 -				width, 1);
    127 -	}
    128 -
    129 -	/* Reset clip to none. */
    130 -	XftDrawSetClip(xw.draw, 0);
    131 +        if (base.mode & ATTR_STRUCK) {
    132 +            XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 3,
    133 +                        width, 1);
    134 +        }
    135 +    }
    136  }
    137  
    138  void
    139 @@ -1524,7 +1518,7 @@ xdrawglyph(Glyph g, int x, int y)
    140  	XftGlyphFontSpec spec;
    141  
    142  	numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y);
    143 -	xdrawglyphfontspecs(&spec, g, numspecs, x, y);
    144 +	xdrawglyphfontspecs(&spec, g, numspecs, x, y, DRAW_BG | DRAW_FG);
    145  }
    146  
    147  void
    148 @@ -1659,32 +1653,39 @@ xstartdraw(void)
    149  void
    150  xdrawline(Line line, int x1, int y1, int x2)
    151  {
    152 -	int i, x, ox, numspecs;
    153 +	int i, x, ox, numspecs, numspecs_cached;
    154  	Glyph base, new;
    155 -	XftGlyphFontSpec *specs = xw.specbuf;
    156 -
    157 -	numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1);
    158 -	i = ox = 0;
    159 -	for (x = x1; x < x2 && i < numspecs; x++) {
    160 -		new = line[x];
    161 -		if (new.mode == ATTR_WDUMMY)
    162 -			continue;
    163 -		if (selected(x, y1))
    164 -			new.mode ^= ATTR_REVERSE;
    165 -		if (i > 0 && ATTRCMP(base, new)) {
    166 -			xdrawglyphfontspecs(specs, base, i, ox, y1);
    167 -			specs += i;
    168 -			numspecs -= i;
    169 -			i = 0;
    170 -		}
    171 -		if (i == 0) {
    172 -			ox = x;
    173 -			base = new;
    174 +	XftGlyphFontSpec *specs;
    175 +
    176 +	numspecs_cached = xmakeglyphfontspecs(xw.specbuf, &line[x1], x2 - x1, x1, y1);
    177 +
    178 +	/* Draw line in 2 passes: background and foreground. This way wide glyphs
    179 +       won't get truncated (#223) */
    180 +	for (int dmode = DRAW_BG; dmode <= DRAW_FG; dmode <<= 1) {
    181 +		specs = xw.specbuf;
    182 +		numspecs = numspecs_cached;
    183 +		i = ox = 0;
    184 +		for (x = x1; x < x2 && i < numspecs; x++) {
    185 +			new = line[x];
    186 +			if (new.mode == ATTR_WDUMMY)
    187 +				continue;
    188 +			if (selected(x, y1))
    189 +				new.mode ^= ATTR_REVERSE;
    190 +			if (i > 0 && ATTRCMP(base, new)) {
    191 +				xdrawglyphfontspecs(specs, base, i, ox, y1, dmode);
    192 +				specs += i;
    193 +				numspecs -= i;
    194 +				i = 0;
    195 +			}
    196 +			if (i == 0) {
    197 +				ox = x;
    198 +				base = new;
    199 +			}
    200 +			i++;
    201  		}
    202 -		i++;
    203 +		if (i > 0)
    204 +			xdrawglyphfontspecs(specs, base, i, ox, y1, dmode);
    205  	}
    206 -	if (i > 0)
    207 -		xdrawglyphfontspecs(specs, base, i, ox, y1);
    208  }
    209  
    210  void
    211 -- 
    212 2.35.1
    213