Introduction
Introduction Statistics Contact Development Disclaimer Help
st-ligatures-scrollback-20210824-0.8.4.diff - sites - public wiki contents of s…
git clone git://git.suckless.org/sites
Log
Files
Refs
---
st-ligatures-scrollback-20210824-0.8.4.diff (8249B)
---
1 diff --git a/Makefile b/Makefile
2 index 470ac86..38240da 100644
3 --- a/Makefile
4 +++ b/Makefile
5 @@ -4,7 +4,7 @@
6
7 include config.mk
8
9 -SRC = st.c x.c
10 +SRC = st.c x.c hb.c
11 OBJ = $(SRC:.c=.o)
12
13 all: options st
14 @@ -22,7 +22,8 @@ config.h:
15 $(CC) $(STCFLAGS) -c $<
16
17 st.o: config.h st.h win.h
18 -x.o: arg.h config.h st.h win.h
19 +x.o: arg.h config.h st.h win.h hb.h
20 +hb.o: st.h
21
22 $(OBJ): config.h config.mk
23
24 diff --git a/config.mk b/config.mk
25 index c070a4a..3d236f0 100644
26 --- a/config.mk
27 +++ b/config.mk
28 @@ -15,10 +15,12 @@ PKG_CONFIG = pkg-config
29 # includes and libs
30 INCS = -I$(X11INC) \
31 `$(PKG_CONFIG) --cflags fontconfig` \
32 - `$(PKG_CONFIG) --cflags freetype2`
33 + `$(PKG_CONFIG) --cflags freetype2` \
34 + `$(PKG_CONFIG) --cflags harfbuzz`
35 LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft \
36 `$(PKG_CONFIG) --libs fontconfig` \
37 - `$(PKG_CONFIG) --libs freetype2`
38 + `$(PKG_CONFIG) --libs freetype2` \
39 + `$(PKG_CONFIG) --libs harfbuzz`
40
41 # flags
42 STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600
43 diff --git a/hb.c b/hb.c
44 new file mode 100644
45 index 0000000..f9c4f76
46 --- /dev/null
47 +++ b/hb.c
48 @@ -0,0 +1,145 @@
49 +#include <stdlib.h>
50 +#include <stdio.h>
51 +#include <math.h>
52 +#include <X11/Xft/Xft.h>
53 +#include <hb.h>
54 +#include <hb-ft.h>
55 +
56 +#include "st.h"
57 +
58 +#define FEATURE(c1,c2,c3,c4) { .tag = HB_TAG(c1,c2,c3,c4), .value = 1, …
59 +
60 +void hbtransformsegment(XftFont *xfont, const Glyph *string, hb_codepoi…
61 +hb_font_t *hbfindfont(XftFont *match);
62 +
63 +typedef struct {
64 + XftFont *match;
65 + hb_font_t *font;
66 +} HbFontMatch;
67 +
68 +static int hbfontslen = 0;
69 +static HbFontMatch *hbfontcache = NULL;
70 +
71 +/*
72 + * Poplulate the array with a list of font features, wrapped in FEATURE…
73 + * e. g.
74 + * FEATURE('c', 'a', 'l', 't'), FEATURE('d', 'l', 'i', 'g')
75 + */
76 +hb_feature_t features[] = { };
77 +
78 +void
79 +hbunloadfonts()
80 +{
81 + for (int i = 0; i < hbfontslen; i++) {
82 + hb_font_destroy(hbfontcache[i].font);
83 + XftUnlockFace(hbfontcache[i].match);
84 + }
85 +
86 + if (hbfontcache != NULL) {
87 + free(hbfontcache);
88 + hbfontcache = NULL;
89 + }
90 + hbfontslen = 0;
91 +}
92 +
93 +hb_font_t *
94 +hbfindfont(XftFont *match)
95 +{
96 + for (int i = 0; i < hbfontslen; i++) {
97 + if (hbfontcache[i].match == match)
98 + return hbfontcache[i].font;
99 + }
100 +
101 + /* Font not found in cache, caching it now. */
102 + hbfontcache = realloc(hbfontcache, sizeof(HbFontMatch) * (hbfon…
103 + FT_Face face = XftLockFace(match);
104 + hb_font_t *font = hb_ft_font_create(face, NULL);
105 + if (font == NULL)
106 + die("Failed to load Harfbuzz font.");
107 +
108 + hbfontcache[hbfontslen].match = match;
109 + hbfontcache[hbfontslen].font = font;
110 + hbfontslen += 1;
111 +
112 + return font;
113 +}
114 +
115 +void
116 +hbtransform(XftGlyphFontSpec *specs, const Glyph *glyphs, size_t len, i…
117 +{
118 + int start = 0, length = 1, gstart = 0;
119 + hb_codepoint_t *codepoints = calloc((unsigned int)len, sizeof(h…
120 +
121 + for (int idx = 1, specidx = 1; idx < len; idx++) {
122 + if (glyphs[idx].mode & ATTR_WDUMMY) {
123 + length += 1;
124 + continue;
125 + }
126 +
127 + if (specs[specidx].font != specs[start].font || ATTRCMP…
128 + hbtransformsegment(specs[start].font, glyphs, c…
129 +
130 + /* Reset the sequence. */
131 + length = 1;
132 + start = specidx;
133 + gstart = idx;
134 + } else {
135 + length += 1;
136 + }
137 +
138 + specidx++;
139 + }
140 +
141 + /* EOL. */
142 + hbtransformsegment(specs[start].font, glyphs, codepoints, gstar…
143 +
144 + /* Apply the transformation to glyph specs. */
145 + for (int i = 0, specidx = 0; i < len; i++) {
146 + if (glyphs[i].mode & ATTR_WDUMMY)
147 + continue;
148 +
149 + if (codepoints[i] != specs[specidx].glyph)
150 + ((Glyph *)glyphs)[i].mode |= ATTR_LIGA;
151 +
152 + specs[specidx++].glyph = codepoints[i];
153 + }
154 +
155 + free(codepoints);
156 +}
157 +
158 +void
159 +hbtransformsegment(XftFont *xfont, const Glyph *string, hb_codepoint_t …
160 +{
161 + hb_font_t *font = hbfindfont(xfont);
162 + if (font == NULL)
163 + return;
164 +
165 + Rune rune;
166 + ushort mode = USHRT_MAX;
167 + hb_buffer_t *buffer = hb_buffer_create();
168 + hb_buffer_set_direction(buffer, HB_DIRECTION_LTR);
169 +
170 + /* Fill buffer with codepoints. */
171 + for (int i = start; i < (start+length); i++) {
172 + rune = string[i].u;
173 + mode = string[i].mode;
174 + if (mode & ATTR_WDUMMY)
175 + rune = 0x0020;
176 + hb_buffer_add_codepoints(buffer, &rune, 1, 0, 1);
177 + }
178 +
179 + /* Shape the segment. */
180 + hb_shape(font, buffer, features, sizeof(features)/sizeof(hb_fea…
181 +
182 + /* Get new glyph info. */
183 + hb_glyph_info_t *info = hb_buffer_get_glyph_infos(buffer, NULL);
184 +
185 + /* Write new codepoints. */
186 + for (int i = 0; i < length; i++) {
187 + hb_codepoint_t gid = info[i].codepoint;
188 + codepoints[start+i] = gid;
189 + }
190 +
191 + /* Cleanup. */
192 + hb_buffer_destroy(buffer);
193 +}
194 diff --git a/hb.h b/hb.h
195 new file mode 100644
196 index 0000000..07888df
197 --- /dev/null
198 +++ b/hb.h
199 @@ -0,0 +1,6 @@
200 +#include <X11/Xft/Xft.h>
201 +#include <hb.h>
202 +#include <hb-ft.h>
203 +
204 +void hbunloadfonts();
205 +void hbtransform(XftGlyphFontSpec *, const Glyph *, size_t, int, int);
206 diff --git a/st.c b/st.c
207 index edec064..ea13c13 100644
208 --- a/st.c
209 +++ b/st.c
210 @@ -2652,7 +2652,8 @@ draw(void)
211 drawregion(0, 0, term.col, term.row);
212 if (term.scr == 0)
213 xdrawcursor(cx, term.c.y, term.line[term.c.y][cx],
214 - term.ocx, term.ocy, term.line[term.ocy]…
215 + term.ocx, term.ocy, term.line[term.ocy]…
216 + term.line[term.ocy], term.col);
217 term.ocx = cx;
218 term.ocy = term.c.y;
219 xfinishdraw();
220 diff --git a/st.h b/st.h
221 index f44e1d3..00c796c 100644
222 --- a/st.h
223 +++ b/st.h
224 @@ -11,7 +11,8 @@
225 #define DIVCEIL(n, d) (((n) + ((d) - 1)) / (d))
226 #define DEFAULT(a, b) (a) = (a) ? (a) : (b)
227 #define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b)…
228 -#define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg !=…
229 +#define ATTRCMP(a, b) (((a).mode & (~ATTR_WRAP) & (~ATTR…
230 + (a).fg != (b).fg || \
231 (a).bg != (b).bg)
232 #define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + \
233 (t1.tv_nsec-t2.tv_nsec)/1E6)
234 @@ -33,6 +34,7 @@ enum glyph_attribute {
235 ATTR_WRAP = 1 << 8,
236 ATTR_WIDE = 1 << 9,
237 ATTR_WDUMMY = 1 << 10,
238 + ATTR_LIGA = 1 << 11,
239 ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
240 };
241
242 diff --git a/win.h b/win.h
243 index a6ef1b9..bc0d180 100644
244 --- a/win.h
245 +++ b/win.h
246 @@ -25,7 +25,7 @@ enum win_mode {
247
248 void xbell(void);
249 void xclipcopy(void);
250 -void xdrawcursor(int, int, Glyph, int, int, Glyph);
251 +void xdrawcursor(int, int, Glyph, int, int, Glyph, Line, int);
252 void xdrawline(Line, int, int, int);
253 void xfinishdraw(void);
254 void xloadcols(void);
255 diff --git a/x.c b/x.c
256 index 210f184..f6d67ef 100644
257 --- a/x.c
258 +++ b/x.c
259 @@ -19,6 +19,7 @@ char *argv0;
260 #include "arg.h"
261 #include "st.h"
262 #include "win.h"
263 +#include "hb.h"
264
265 /* types used in config.h */
266 typedef struct {
267 @@ -1031,6 +1032,9 @@ xunloadfont(Font *f)
268 void
269 xunloadfonts(void)
270 {
271 + /* Clear Harfbuzz font cache. */
272 + hbunloadfonts();
273 +
274 /* Free the loaded fonts in the font cache. */
275 while (frclen > 0)
276 XftFontClose(xw.dpy, frc[--frclen].font);
277 @@ -1229,7 +1233,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const…
278 mode = glyphs[i].mode;
279
280 /* Skip dummy wide-character spacing. */
281 - if (mode == ATTR_WDUMMY)
282 + if (mode & ATTR_WDUMMY)
283 continue;
284
285 /* Determine font for glyph if different from previous …
286 @@ -1336,6 +1340,9 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const…
287 numspecs++;
288 }
289
290 + /* Harfbuzz transformation for ligatures. */
291 + hbtransform(specs, glyphs, len, x, y);
292 +
293 return numspecs;
294 }
295
296 @@ -1485,14 +1492,17 @@ xdrawglyph(Glyph g, int x, int y)
297 }
298
299 void
300 -xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og)
301 +xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line lin…
302 {
303 Color drawcol;
304
305 /* remove the old cursor */
306 if (selected(ox, oy))
307 og.mode ^= ATTR_REVERSE;
308 - xdrawglyph(og, ox, oy);
309 +
310 + /* Redraw the line where cursor was previously.
311 + * It will restore the ligatures broken by the cursor. */
312 + xdrawline(line, 0, oy, len);
313
314 if (IS_SET(MODE_HIDE))
315 return;
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.