|
| 1 | +From 37567786b543aacd172c7cd095ce862568ca46f0 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Iskustvo < [email protected]> |
| 3 | +Date: Sat, 7 Jan 2023 03:37:22 +0100 |
| 4 | +Subject: [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 d756be1..e6ea1a0 100644 |
| 15 | +--- a/st.c |
| 16 | ++++ b/st.c |
| 17 | +@@ -2801,7 +2801,8 @@ draw(void) |
| 18 | + drawregion(0, 0, term.col, term.row); |
| 19 | + if (TSCREEN.off == 0) |
| 20 | + xdrawcursor(cx, term.c.y, TLINE(term.c.y)[cx], |
| 21 | +- term.ocx, term.ocy, TLINE(term.ocy)[term.ocx]); |
| 22 | ++ term.ocx, term.ocy, TLINE(term.ocy)[term.ocx], |
| 23 | ++ TLINE(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 8471441..2c71ec8 100644 |
| 29 | +--- a/st.h |
| 30 | ++++ b/st.h |
| 31 | +@@ -37,6 +37,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 cd4bd94..b8c4d93 100644 |
| 59 | +--- a/x.c |
| 60 | ++++ b/x.c |
| 61 | +@@ -145,7 +145,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 | +@@ -1375,7 +1375,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 | +@@ -1462,47 +1462,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 | +@@ -1512,11 +1505,11 @@ 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 | + XRenderColor colbg; |
| 175 | +@@ -1524,7 +1517,10 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) |
| 176 | + /* remove the old cursor */ |
| 177 | + if (selected(ox, oy)) |
| 178 | + og.mode ^= ATTR_REVERSE; |
| 179 | +- xdrawglyph(og, ox, oy); |
| 180 | ++ |
| 181 | ++ /* Redraw the line where cursor was previously. |
| 182 | ++ * It will restore wide glyphs and ligatures broken by the cursor. */ |
| 183 | ++ xdrawline(line, 0, oy, len); |
| 184 | + |
| 185 | + if (IS_SET(MODE_HIDE)) |
| 186 | + return; |
| 187 | +@@ -1662,32 +1658,39 @@ xstartdraw(void) |
| 188 | + void |
| 189 | + xdrawline(Line line, int x1, int y1, int x2) |
| 190 | + { |
| 191 | +- int i, x, ox, numspecs; |
| 192 | ++ int i, x, ox, numspecs, numspecs_cached; |
| 193 | + Glyph base, new; |
| 194 | +- XftGlyphFontSpec *specs = xw.specbuf; |
| 195 | +- |
| 196 | +- numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1); |
| 197 | +- i = ox = 0; |
| 198 | +- for (x = x1; x < x2 && i < numspecs; x++) { |
| 199 | +- new = line[x]; |
| 200 | +- if (new.mode == ATTR_WDUMMY) |
| 201 | +- continue; |
| 202 | +- if (selected(x, y1)) |
| 203 | +- new.mode ^= ATTR_REVERSE; |
| 204 | +- if (i > 0 && ATTRCMP(base, new)) { |
| 205 | +- xdrawglyphfontspecs(specs, base, i, ox, y1); |
| 206 | +- specs += i; |
| 207 | +- numspecs -= i; |
| 208 | +- i = 0; |
| 209 | +- } |
| 210 | +- if (i == 0) { |
| 211 | +- ox = x; |
| 212 | +- base = new; |
| 213 | ++ XftGlyphFontSpec *specs; |
| 214 | ++ |
| 215 | ++ numspecs_cached = xmakeglyphfontspecs(xw.specbuf, &line[x1], x2 - x1, x1, y1); |
| 216 | ++ |
| 217 | ++ /* Draw line in 2 passes: background and foreground. This way wide glyphs |
| 218 | ++ won't get truncated (#223) */ |
| 219 | ++ for (int dmode = DRAW_BG; dmode <= DRAW_FG; dmode <<= 1) { |
| 220 | ++ specs = xw.specbuf; |
| 221 | ++ numspecs = numspecs_cached; |
| 222 | ++ i = ox = 0; |
| 223 | ++ for (x = x1; x < x2 && i < numspecs; x++) { |
| 224 | ++ new = line[x]; |
| 225 | ++ if (new.mode == ATTR_WDUMMY) |
| 226 | ++ continue; |
| 227 | ++ if (selected(x, y1)) |
| 228 | ++ new.mode ^= ATTR_REVERSE; |
| 229 | ++ if (i > 0 && ATTRCMP(base, new)) { |
| 230 | ++ xdrawglyphfontspecs(specs, base, i, ox, y1, dmode); |
| 231 | ++ specs += i; |
| 232 | ++ numspecs -= i; |
| 233 | ++ i = 0; |
| 234 | ++ } |
| 235 | ++ if (i == 0) { |
| 236 | ++ ox = x; |
| 237 | ++ base = new; |
| 238 | ++ } |
| 239 | ++ i++; |
| 240 | + } |
| 241 | +- i++; |
| 242 | ++ if (i > 0) |
| 243 | ++ xdrawglyphfontspecs(specs, base, i, ox, y1, dmode); |
| 244 | + } |
| 245 | +- if (i > 0) |
| 246 | +- xdrawglyphfontspecs(specs, base, i, ox, y1); |
| 247 | + } |
| 248 | + |
| 249 | + void |
| 250 | +-- |
| 251 | +2.39.0 |
| 252 | + |
0 commit comments