Introduction
Introduction Statistics Contact Development Disclaimer Help
st-ligatures-alpha-scrollback-20200428-28ad288.diff - sites - public wiki conte…
git clone git://git.suckless.org/sites
Log
Files
Refs
---
st-ligatures-alpha-scrollback-20200428-28ad288.diff (7908B)
---
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 1d2f0e2..fd92921 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 -lXrender\
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..bd3fb71
46 --- /dev/null
47 +++ b/hb.c
48 @@ -0,0 +1,136 @@
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 +void hbtransformsegment(XftFont *xfont, const Glyph *string, hb_codepoi…
59 +hb_font_t *hbfindfont(XftFont *match);
60 +
61 +typedef struct {
62 + XftFont *match;
63 + hb_font_t *font;
64 +} HbFontMatch;
65 +
66 +static int hbfontslen = 0;
67 +static HbFontMatch *hbfontcache = NULL;
68 +
69 +void
70 +hbunloadfonts()
71 +{
72 + for (int i = 0; i < hbfontslen; i++) {
73 + hb_font_destroy(hbfontcache[i].font);
74 + XftUnlockFace(hbfontcache[i].match);
75 + }
76 +
77 + if (hbfontcache != NULL) {
78 + free(hbfontcache);
79 + hbfontcache = NULL;
80 + }
81 + hbfontslen = 0;
82 +}
83 +
84 +hb_font_t *
85 +hbfindfont(XftFont *match)
86 +{
87 + for (int i = 0; i < hbfontslen; i++) {
88 + if (hbfontcache[i].match == match)
89 + return hbfontcache[i].font;
90 + }
91 +
92 + /* Font not found in cache, caching it now. */
93 + hbfontcache = realloc(hbfontcache, sizeof(HbFontMatch) * (hbfon…
94 + FT_Face face = XftLockFace(match);
95 + hb_font_t *font = hb_ft_font_create(face, NULL);
96 + if (font == NULL)
97 + die("Failed to load Harfbuzz font.");
98 +
99 + hbfontcache[hbfontslen].match = match;
100 + hbfontcache[hbfontslen].font = font;
101 + hbfontslen += 1;
102 +
103 + return font;
104 +}
105 +
106 +void
107 +hbtransform(XftGlyphFontSpec *specs, const Glyph *glyphs, size_t len, i…
108 +{
109 + int start = 0, length = 1, gstart = 0;
110 + hb_codepoint_t *codepoints = calloc(len, sizeof(hb_codepoint_t)…
111 +
112 + for (int idx = 1, specidx = 1; idx < len; idx++) {
113 + if (glyphs[idx].mode & ATTR_WDUMMY) {
114 + length += 1;
115 + continue;
116 + }
117 +
118 + if (specs[specidx].font != specs[start].font || ATTRCMP…
119 + hbtransformsegment(specs[start].font, glyphs, c…
120 +
121 + /* Reset the sequence. */
122 + length = 1;
123 + start = specidx;
124 + gstart = idx;
125 + } else {
126 + length += 1;
127 + }
128 +
129 + specidx++;
130 + }
131 +
132 + /* EOL. */
133 + hbtransformsegment(specs[start].font, glyphs, codepoints, gstar…
134 +
135 + /* Apply the transformation to glyph specs. */
136 + for (int i = 0, specidx = 0; i < len; i++) {
137 + if (glyphs[i].mode & ATTR_WDUMMY)
138 + continue;
139 +
140 + if (codepoints[i] != specs[specidx].glyph)
141 + ((Glyph *)glyphs)[i].mode |= ATTR_LIGA;
142 +
143 + specs[specidx++].glyph = codepoints[i];
144 + }
145 +
146 + free(codepoints);
147 +}
148 +
149 +void
150 +hbtransformsegment(XftFont *xfont, const Glyph *string, hb_codepoint_t …
151 +{
152 + hb_font_t *font = hbfindfont(xfont);
153 + if (font == NULL)
154 + return;
155 +
156 + Rune rune;
157 + ushort mode = USHRT_MAX;
158 + hb_buffer_t *buffer = hb_buffer_create();
159 + hb_buffer_set_direction(buffer, HB_DIRECTION_LTR);
160 +
161 + /* Fill buffer with codepoints. */
162 + for (int i = start; i < (start+length); i++) {
163 + rune = string[i].u;
164 + mode = string[i].mode;
165 + if (mode & ATTR_WDUMMY)
166 + rune = 0x0020;
167 + hb_buffer_add_codepoints(buffer, &rune, 1, 0, 1);
168 + }
169 +
170 + /* Shape the segment. */
171 + hb_shape(font, buffer, NULL, 0);
172 +
173 + /* Get new glyph info. */
174 + hb_glyph_info_t *info = hb_buffer_get_glyph_infos(buffer, NULL);
175 +
176 + /* Write new codepoints. */
177 + for (int i = 0; i < length; i++) {
178 + hb_codepoint_t gid = info[i].codepoint;
179 + codepoints[start+i] = gid;
180 + }
181 +
182 + /* Cleanup. */
183 + hb_buffer_destroy(buffer);
184 +}
185 diff --git a/hb.h b/hb.h
186 new file mode 100644
187 index 0000000..a209238
188 --- /dev/null
189 +++ b/hb.h
190 @@ -0,0 +1,7 @@
191 +#include <X11/Xft/Xft.h>
192 +#include <hb.h>
193 +#include <hb-ft.h>
194 +
195 +void hbunloadfonts();
196 +void hbtransform(XftGlyphFontSpec *, const Glyph *, size_t, int, int);
197 +
198 diff --git a/st.c b/st.c
199 index f8b6f67..a6c3ee7 100644
200 --- a/st.c
201 +++ b/st.c
202 @@ -2656,7 +2656,8 @@ draw(void)
203 drawregion(0, 0, term.col, term.row);
204 if (term.scr == 0)
205 xdrawcursor(cx, term.c.y, term.line[term.c.y][cx],
206 - term.ocx, term.ocy, term.line[term.ocy]…
207 + term.ocx, term.ocy, term.line[term.ocy]…
208 + term.line[term.ocy], term.col);
209 term.ocx = cx, term.ocy = term.c.y;
210 xfinishdraw();
211 xximspot(term.ocx, term.ocy);
212 diff --git a/st.h b/st.h
213 index c67ebc3..073ae82 100644
214 --- a/st.h
215 +++ b/st.h
216 @@ -11,7 +11,8 @@
217 #define DIVCEIL(n, d) (((n) + ((d) - 1)) / (d))
218 #define DEFAULT(a, b) (a) = (a) ? (a) : (b)
219 #define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b)…
220 -#define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg !=…
221 +#define ATTRCMP(a, b) (((a).mode & (~ATTR_WRAP) & (~ATTR…
222 + (a).fg != (b).fg || \
223 (a).bg != (b).bg)
224 #define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + \
225 (t1.tv_nsec-t2.tv_nsec)/1E6)
226 @@ -33,6 +34,7 @@ enum glyph_attribute {
227 ATTR_WRAP = 1 << 8,
228 ATTR_WIDE = 1 << 9,
229 ATTR_WDUMMY = 1 << 10,
230 + ATTR_LIGA = 1 << 11,
231 ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
232 };
233
234 diff --git a/win.h b/win.h
235 index a6ef1b9..bc0d180 100644
236 --- a/win.h
237 +++ b/win.h
238 @@ -25,7 +25,7 @@ enum win_mode {
239
240 void xbell(void);
241 void xclipcopy(void);
242 -void xdrawcursor(int, int, Glyph, int, int, Glyph);
243 +void xdrawcursor(int, int, Glyph, int, int, Glyph, Line, int);
244 void xdrawline(Line, int, int, int);
245 void xfinishdraw(void);
246 void xloadcols(void);
247 diff --git a/x.c b/x.c
248 index 139f7ff..eaf764f 100644
249 --- a/x.c
250 +++ b/x.c
251 @@ -19,6 +19,7 @@ static char *argv0;
252 #include "arg.h"
253 #include "st.h"
254 #include "win.h"
255 +#include "hb.h"
256
257 /* types used in config.h */
258 typedef struct {
259 @@ -1040,6 +1041,9 @@ xunloadfont(Font *f)
260 void
261 xunloadfonts(void)
262 {
263 + /* Clear Harfbuzz font cache. */
264 + hbunloadfonts();
265 +
266 /* Free the loaded fonts in the font cache. */
267 while (frclen > 0)
268 XftFontClose(xw.dpy, frc[--frclen].font);
269 @@ -1246,7 +1250,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const…
270 mode = glyphs[i].mode;
271
272 /* Skip dummy wide-character spacing. */
273 - if (mode == ATTR_WDUMMY)
274 + if (mode & ATTR_WDUMMY)
275 continue;
276
277 /* Determine font for glyph if different from previous …
278 @@ -1353,6 +1357,9 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const…
279 numspecs++;
280 }
281
282 + /* Harfbuzz transformation for ligatures. */
283 + hbtransform(specs, glyphs, len, x, y);
284 +
285 return numspecs;
286 }
287
288 @@ -1502,14 +1509,17 @@ xdrawglyph(Glyph g, int x, int y)
289 }
290
291 void
292 -xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og)
293 +xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line lin…
294 {
295 Color drawcol;
296
297 /* remove the old cursor */
298 if (selected(ox, oy))
299 og.mode ^= ATTR_REVERSE;
300 - xdrawglyph(og, ox, oy);
301 +
302 + /* Redraw the line where cursor was previously.
303 + * It will restore the ligatures broken by the cursor. */
304 + xdrawline(line, 0, oy, len);
305
306 if (IS_SET(MODE_HIDE))
307 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.