Skip to content

Commit 6595448

Browse files
author
Iskustvo
committed
feat: add wide glyph support
Unofficial patch: https://lists.suckless.org/wiki/2301/4571.html For more information, read: LukeSmithxyz/st#349
1 parent 91c1886 commit 6595448

File tree

1 file changed

+252
-0
lines changed

1 file changed

+252
-0
lines changed
Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
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

Comments
 (0)