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