sites

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

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


      1 From 68de38fadd04f2f454bceccea0fccc8276b635cb Mon Sep 17 00:00:00 2001
      2 From: wael <40663@protonmail.com>
      3 Date: Mon, 11 Apr 2022 16:45:49 +0300
      4 Subject: [PATCH] add glyph wide support patch
      5 
      6 ---
      7  st.h |   6 +++
      8  x.c  | 134 +++++++++++++++++++++++++++++------------------------------
      9  2 files changed, 73 insertions(+), 67 deletions(-)
     10 
     11 diff --git a/st.h b/st.h
     12 index 519b9bd..4f74621 100644
     13 --- a/st.h
     14 +++ b/st.h
     15 @@ -36,6 +36,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 2a3bd38..d60df52 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 @@ -1372,7 +1372,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 @@ -1463,47 +1463,40 @@ 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 -	/* Render the glyphs. */
     80 -	XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
     81 -
     82 -	/* Render underline and strikethrough. */
     83 -	if (base.mode & ATTR_UNDERLINE) {
     84 -		XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent * chscale + 1,
     85 -				width, 1);
     86 -	}
     87 -
     88 -	if (base.mode & ATTR_STRUCK) {
     89 -		XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent * chscale / 3,
     90 -				width, 1);
     91 -	}
     92 -
     93 -	/* Reset clip to none. */
     94 -	XftDrawSetClip(xw.draw, 0);
     95 +    if (dmode & DRAW_BG) {
     96 +        /* Intelligent cleaning up of the borders. */
     97 +        if (x == 0) {
     98 +            xclear(0, (y == 0)? 0 : winy, borderpx,
     99 +                   winy + win.ch +
    100 +                   ((winy + win.ch >= borderpx + win.th)? win.h : 0));
    101 +        }
    102 +        if (winx + width >= borderpx + win.tw) {
    103 +            xclear(winx + width, (y == 0)? 0 : winy, win.w,
    104 +                   ((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch)));
    105 +        }
    106 +        if (y == 0)
    107 +            xclear(winx, 0, winx + width, borderpx);
    108 +        if (winy + win.ch >= borderpx + win.th)
    109 +            xclear(winx, winy + win.ch, winx + width, win.h);
    110 +        /* Fill the background */
    111 +        XftDrawRect(xw.draw, bg, winx, winy, width, win.ch);
    112 +    }
    113 +
    114 +    if (dmode & DRAW_FG) {
    115 +        /* Render the glyphs. */
    116 +        XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
    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 / 3,
    126 +                        width, 1);
    127 +        }
    128 +    }
    129  }
    130  
    131  void
    132 @@ -1513,7 +1506,7 @@ xdrawglyph(Glyph g, int x, int y)
    133  	XftGlyphFontSpec spec;
    134  
    135  	numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y);
    136 -	xdrawglyphfontspecs(&spec, g, numspecs, x, y);
    137 +	xdrawglyphfontspecs(&spec, g, numspecs, x, y, DRAW_BG | DRAW_FG);
    138  }
    139  
    140  void
    141 @@ -1648,32 +1641,39 @@ xstartdraw(void)
    142  void
    143  xdrawline(Line line, int x1, int y1, int x2)
    144  {
    145 -	int i, x, ox, numspecs;
    146 +	int i, x, ox, numspecs, numspecs_cached;
    147  	Glyph base, new;
    148 -	XftGlyphFontSpec *specs = xw.specbuf;
    149 -
    150 -	numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1);
    151 -	i = ox = 0;
    152 -	for (x = x1; x < x2 && i < numspecs; x++) {
    153 -		new = line[x];
    154 -		if (new.mode == ATTR_WDUMMY)
    155 -			continue;
    156 -		if (selected(x, y1))
    157 -			new.mode ^= ATTR_REVERSE;
    158 -		if (i > 0 && ATTRCMP(base, new)) {
    159 -			xdrawglyphfontspecs(specs, base, i, ox, y1);
    160 -			specs += i;
    161 -			numspecs -= i;
    162 -			i = 0;
    163 -		}
    164 -		if (i == 0) {
    165 -			ox = x;
    166 -			base = new;
    167 +	XftGlyphFontSpec *specs;
    168 +
    169 +	numspecs_cached = xmakeglyphfontspecs(xw.specbuf, &line[x1], x2 - x1, x1, y1);
    170 +
    171 +	/* Draw line in 2 passes: background and foreground. This way wide glyphs
    172 +       won't get truncated (#223) */
    173 +	for (int dmode = DRAW_BG; dmode <= DRAW_FG; dmode <<= 1) {
    174 +		specs = xw.specbuf;
    175 +		numspecs = numspecs_cached;
    176 +		i = ox = 0;
    177 +		for (x = x1; x < x2 && i < numspecs; x++) {
    178 +			new = line[x];
    179 +			if (new.mode == ATTR_WDUMMY)
    180 +				continue;
    181 +			if (selected(x, y1))
    182 +				new.mode ^= ATTR_REVERSE;
    183 +			if (i > 0 && ATTRCMP(base, new)) {
    184 +				xdrawglyphfontspecs(specs, base, i, ox, y1, dmode);
    185 +				specs += i;
    186 +				numspecs -= i;
    187 +				i = 0;
    188 +			}
    189 +			if (i == 0) {
    190 +				ox = x;
    191 +				base = new;
    192 +			}
    193 +			i++;
    194  		}
    195 -		i++;
    196 +		if (i > 0)
    197 +			xdrawglyphfontspecs(specs, base, i, ox, y1, dmode);
    198  	}
    199 -	if (i > 0)
    200 -		xdrawglyphfontspecs(specs, base, i, ox, y1);
    201  }
    202  
    203  void
    204 -- 
    205 2.35.1
    206