sites

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

st-glyph-wide-support-20230701-5770f2f.diff (7400B)


      1 From 5770f2fc02afca341c275fc340bbc5003ecc3df8 Mon Sep 17 00:00:00 2001
      2 From: Iskustvo <iskustvo@yahoo.com>
      3 Date: Sat, 7 Jan 2023 01:23:37 +0100
      4 Subject: [PATCH] [PATCH] add glyph wide support patch
      5 
      6 ---
      7  st.c  |   3 +-
      8  st.h  |   6 +++
      9  win.h |   2 +-
     10  x.c   | 141 ++++++++++++++++++++++++++++++----------------------------
     11  4 files changed, 81 insertions(+), 71 deletions(-)
     12 
     13 diff --git a/st.c b/st.c
     14 index 62def59..cc6c78e 100644
     15 --- a/st.c
     16 +++ b/st.c
     17 @@ -2640,7 +2640,8 @@ draw(void)
     18  
     19  	drawregion(0, 0, term.col, term.row);
     20  	xdrawcursor(cx, term.c.y, term.line[term.c.y][cx],
     21 -			term.ocx, term.ocy, term.line[term.ocy][term.ocx]);
     22 +		term.ocx, term.ocy, term.line[term.ocy][term.ocx],
     23 +		term.line[term.ocy], term.col);
     24  	term.ocx = cx;
     25  	term.ocy = term.c.y;
     26  	xfinishdraw();
     27 diff --git a/st.h b/st.h
     28 index fd3b0d8..0053050 100644
     29 --- a/st.h
     30 +++ b/st.h
     31 @@ -36,6 +36,12 @@ enum glyph_attribute {
     32  	ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
     33  };
     34  
     35 +enum drawing_mode {
     36 +    DRAW_NONE = 0,
     37 +    DRAW_BG = 1 << 0,
     38 +    DRAW_FG = 1 << 1,
     39 +};
     40 +
     41  enum selection_mode {
     42  	SEL_IDLE = 0,
     43  	SEL_EMPTY = 1,
     44 diff --git a/win.h b/win.h
     45 index 6de960d..94679e4 100644
     46 --- a/win.h
     47 +++ b/win.h
     48 @@ -25,7 +25,7 @@ enum win_mode {
     49  
     50  void xbell(void);
     51  void xclipcopy(void);
     52 -void xdrawcursor(int, int, Glyph, int, int, Glyph);
     53 +void xdrawcursor(int, int, Glyph, int, int, Glyph, Line, int);
     54  void xdrawline(Line, int, int, int);
     55  void xfinishdraw(void);
     56  void xloadcols(void);
     57 diff --git a/x.c b/x.c
     58 index aa09997..85deee6 100644
     59 --- a/x.c
     60 +++ b/x.c
     61 @@ -142,7 +142,7 @@ typedef struct {
     62  
     63  static inline ushort sixd_to_16bit(int);
     64  static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int);
     65 -static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int);
     66 +static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int, int);
     67  static void xdrawglyph(Glyph, int, int);
     68  static void xclear(int, int, int, int);
     69  static int xgeommasktogravity(int);
     70 @@ -1372,7 +1372,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
     71  }
     72  
     73  void
     74 -xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y)
     75 +xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y, int dmode)
     76  {
     77  	int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1);
     78  	int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch,
     79 @@ -1463,47 +1463,40 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
     80  	if (base.mode & ATTR_INVISIBLE)
     81  		fg = bg;
     82  
     83 -	/* Intelligent cleaning up of the borders. */
     84 -	if (x == 0) {
     85 -		xclear(0, (y == 0)? 0 : winy, borderpx,
     86 -			winy + win.ch +
     87 -			((winy + win.ch >= borderpx + win.th)? win.h : 0));
     88 -	}
     89 -	if (winx + width >= borderpx + win.tw) {
     90 -		xclear(winx + width, (y == 0)? 0 : winy, win.w,
     91 -			((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch)));
     92 -	}
     93 -	if (y == 0)
     94 -		xclear(winx, 0, winx + width, borderpx);
     95 -	if (winy + win.ch >= borderpx + win.th)
     96 -		xclear(winx, winy + win.ch, winx + width, win.h);
     97 -
     98 -	/* Clean up the region we want to draw to. */
     99 -	XftDrawRect(xw.draw, bg, winx, winy, width, win.ch);
    100 -
    101 -	/* Set the clip region because Xft is sometimes dirty. */
    102 -	r.x = 0;
    103 -	r.y = 0;
    104 -	r.height = win.ch;
    105 -	r.width = width;
    106 -	XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1);
    107 -
    108 -	/* Render the glyphs. */
    109 -	XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
    110 -
    111 -	/* Render underline and strikethrough. */
    112 -	if (base.mode & ATTR_UNDERLINE) {
    113 -		XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent * chscale + 1,
    114 -				width, 1);
    115 -	}
    116 -
    117 -	if (base.mode & ATTR_STRUCK) {
    118 -		XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent * chscale / 3,
    119 -				width, 1);
    120 -	}
    121 -
    122 -	/* Reset clip to none. */
    123 -	XftDrawSetClip(xw.draw, 0);
    124 +    if (dmode & DRAW_BG) {
    125 +        /* Intelligent cleaning up of the borders. */
    126 +        if (x == 0) {
    127 +            xclear(0, (y == 0)? 0 : winy, borderpx,
    128 +                   winy + win.ch +
    129 +                   ((winy + win.ch >= borderpx + win.th)? win.h : 0));
    130 +        }
    131 +        if (winx + width >= borderpx + win.tw) {
    132 +            xclear(winx + width, (y == 0)? 0 : winy, win.w,
    133 +                   ((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch)));
    134 +        }
    135 +        if (y == 0)
    136 +            xclear(winx, 0, winx + width, borderpx);
    137 +        if (winy + win.ch >= borderpx + win.th)
    138 +            xclear(winx, winy + win.ch, winx + width, win.h);
    139 +        /* Fill the background */
    140 +        XftDrawRect(xw.draw, bg, winx, winy, width, win.ch);
    141 +    }
    142 +
    143 +    if (dmode & DRAW_FG) {
    144 +        /* Render the glyphs. */
    145 +        XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
    146 +
    147 +        /* Render underline and strikethrough. */
    148 +        if (base.mode & ATTR_UNDERLINE) {
    149 +            XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1,
    150 +                        width, 1);
    151 +        }
    152 +
    153 +        if (base.mode & ATTR_STRUCK) {
    154 +            XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 3,
    155 +                        width, 1);
    156 +        }
    157 +    }
    158  }
    159  
    160  void
    161 @@ -1513,18 +1506,21 @@ xdrawglyph(Glyph g, int x, int y)
    162  	XftGlyphFontSpec spec;
    163  
    164  	numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y);
    165 -	xdrawglyphfontspecs(&spec, g, numspecs, x, y);
    166 +	xdrawglyphfontspecs(&spec, g, numspecs, x, y, DRAW_BG | DRAW_FG);
    167  }
    168  
    169  void
    170 -xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og)
    171 +xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line line, int len)
    172  {
    173  	Color drawcol;
    174  
    175  	/* remove the old cursor */
    176  	if (selected(ox, oy))
    177  		og.mode ^= ATTR_REVERSE;
    178 -	xdrawglyph(og, ox, oy);
    179 +
    180 +	/* Redraw the line where cursor was previously.
    181 +	 * It will restore wide glyphs and ligatures broken by the cursor. */
    182 +	xdrawline(line, 0, oy, len);
    183  
    184  	if (IS_SET(MODE_HIDE))
    185  		return;
    186 @@ -1648,32 +1644,39 @@ xstartdraw(void)
    187  void
    188  xdrawline(Line line, int x1, int y1, int x2)
    189  {
    190 -	int i, x, ox, numspecs;
    191 +	int i, x, ox, numspecs, numspecs_cached;
    192  	Glyph base, new;
    193 -	XftGlyphFontSpec *specs = xw.specbuf;
    194 -
    195 -	numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1);
    196 -	i = ox = 0;
    197 -	for (x = x1; x < x2 && i < numspecs; x++) {
    198 -		new = line[x];
    199 -		if (new.mode == ATTR_WDUMMY)
    200 -			continue;
    201 -		if (selected(x, y1))
    202 -			new.mode ^= ATTR_REVERSE;
    203 -		if (i > 0 && ATTRCMP(base, new)) {
    204 -			xdrawglyphfontspecs(specs, base, i, ox, y1);
    205 -			specs += i;
    206 -			numspecs -= i;
    207 -			i = 0;
    208 -		}
    209 -		if (i == 0) {
    210 -			ox = x;
    211 -			base = new;
    212 +	XftGlyphFontSpec *specs;
    213 +
    214 +	numspecs_cached = xmakeglyphfontspecs(xw.specbuf, &line[x1], x2 - x1, x1, y1);
    215 +
    216 +	/* Draw line in 2 passes: background and foreground. This way wide glyphs
    217 +       won't get truncated (#223) */
    218 +	for (int dmode = DRAW_BG; dmode <= DRAW_FG; dmode <<= 1) {
    219 +		specs = xw.specbuf;
    220 +		numspecs = numspecs_cached;
    221 +		i = ox = 0;
    222 +		for (x = x1; x < x2 && i < numspecs; x++) {
    223 +			new = line[x];
    224 +			if (new.mode == ATTR_WDUMMY)
    225 +				continue;
    226 +			if (selected(x, y1))
    227 +				new.mode ^= ATTR_REVERSE;
    228 +			if (i > 0 && ATTRCMP(base, new)) {
    229 +				xdrawglyphfontspecs(specs, base, i, ox, y1, dmode);
    230 +				specs += i;
    231 +				numspecs -= i;
    232 +				i = 0;
    233 +			}
    234 +			if (i == 0) {
    235 +				ox = x;
    236 +				base = new;
    237 +			}
    238 +			i++;
    239  		}
    240 -		i++;
    241 +		if (i > 0)
    242 +			xdrawglyphfontspecs(specs, base, i, ox, y1, dmode);
    243  	}
    244 -	if (i > 0)
    245 -		xdrawglyphfontspecs(specs, base, i, ox, y1);
    246  }
    247  
    248  void
    249 -- 
    250 2.39.0
    251