Introduction
Introduction Statistics Contact Development Disclaimer Help
st-ligatures-boxdraw-20210824-0.8.4.diff - sites - public wiki contents of suck…
git clone git://git.suckless.org/sites
Log
Files
Refs
---
st-ligatures-boxdraw-20210824-0.8.4.diff (8360B)
---
1 diff --git a/Makefile b/Makefile
2 index 6dfa212..2ffd3c8 100644
3 --- a/Makefile
4 +++ b/Makefile
5 @@ -4,7 +4,7 @@
6
7 include config.mk
8
9 -SRC = st.c x.c boxdraw.c
10 +SRC = st.c x.c boxdraw.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 boxdraw.o: config.h st.h boxdraw_data.h
22
23 $(OBJ): config.h config.mk
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..a47300e
46 --- /dev/null
47 +++ b/hb.c
48 @@ -0,0 +1,149 @@
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 + if (glyphs[i].mode & ATTR_BOXDRAW) {
149 + specidx++;
150 + continue;
151 + }
152 +
153 + if (codepoints[i] != specs[specidx].glyph)
154 + ((Glyph *)glyphs)[i].mode |= ATTR_LIGA;
155 +
156 + specs[specidx++].glyph = codepoints[i];
157 + }
158 +
159 + free(codepoints);
160 +}
161 +
162 +void
163 +hbtransformsegment(XftFont *xfont, const Glyph *string, hb_codepoint_t …
164 +{
165 + hb_font_t *font = hbfindfont(xfont);
166 + if (font == NULL)
167 + return;
168 +
169 + Rune rune;
170 + ushort mode = USHRT_MAX;
171 + hb_buffer_t *buffer = hb_buffer_create();
172 + hb_buffer_set_direction(buffer, HB_DIRECTION_LTR);
173 +
174 + /* Fill buffer with codepoints. */
175 + for (int i = start; i < (start+length); i++) {
176 + rune = string[i].u;
177 + mode = string[i].mode;
178 + if (mode & ATTR_WDUMMY)
179 + rune = 0x0020;
180 + hb_buffer_add_codepoints(buffer, &rune, 1, 0, 1);
181 + }
182 +
183 + /* Shape the segment. */
184 + hb_shape(font, buffer, features, sizeof(features)/sizeof(hb_fea…
185 +
186 + /* Get new glyph info. */
187 + hb_glyph_info_t *info = hb_buffer_get_glyph_infos(buffer, NULL);
188 +
189 + /* Write new codepoints. */
190 + for (int i = 0; i < length; i++) {
191 + hb_codepoint_t gid = info[i].codepoint;
192 + codepoints[start+i] = gid;
193 + }
194 +
195 + /* Cleanup. */
196 + hb_buffer_destroy(buffer);
197 +}
198 diff --git a/hb.h b/hb.h
199 new file mode 100644
200 index 0000000..07888df
201 --- /dev/null
202 +++ b/hb.h
203 @@ -0,0 +1,6 @@
204 +#include <X11/Xft/Xft.h>
205 +#include <hb.h>
206 +#include <hb-ft.h>
207 +
208 +void hbunloadfonts();
209 +void hbtransform(XftGlyphFontSpec *, const Glyph *, size_t, int, int);
210 diff --git a/st.c b/st.c
211 index 248728f..9101ae8 100644
212 --- a/st.c
213 +++ b/st.c
214 @@ -2584,7 +2584,8 @@ draw(void)
215
216 drawregion(0, 0, term.col, term.row);
217 xdrawcursor(cx, term.c.y, term.line[term.c.y][cx],
218 - term.ocx, term.ocy, term.line[term.ocy][term.oc…
219 + term.ocx, term.ocy, term.line[term.ocy][term.oc…
220 + term.line[term.ocy], term.col);
221 term.ocx = cx;
222 term.ocy = term.c.y;
223 xfinishdraw();
224 diff --git a/st.h b/st.h
225 index 8d26273..133dc08 100644
226 --- a/st.h
227 +++ b/st.h
228 @@ -11,7 +11,8 @@
229 #define DIVCEIL(n, d) (((n) + ((d) - 1)) / (d))
230 #define DEFAULT(a, b) (a) = (a) ? (a) : (b)
231 #define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b)…
232 -#define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg !=…
233 +#define ATTRCMP(a, b) (((a).mode & (~ATTR_WRAP) & (~ATTR…
234 + (a).fg != (b).fg || \
235 (a).bg != (b).bg)
236 #define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + \
237 (t1.tv_nsec-t2.tv_nsec)/1E6)
238 @@ -34,6 +35,7 @@ enum glyph_attribute {
239 ATTR_WIDE = 1 << 9,
240 ATTR_WDUMMY = 1 << 10,
241 ATTR_BOXDRAW = 1 << 11,
242 + ATTR_LIGA = 1 << 12,
243 ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
244 };
245
246 diff --git a/win.h b/win.h
247 index a6ef1b9..bc0d180 100644
248 --- a/win.h
249 +++ b/win.h
250 @@ -25,7 +25,7 @@ enum win_mode {
251
252 void xbell(void);
253 void xclipcopy(void);
254 -void xdrawcursor(int, int, Glyph, int, int, Glyph);
255 +void xdrawcursor(int, int, Glyph, int, int, Glyph, Line, int);
256 void xdrawline(Line, int, int, int);
257 void xfinishdraw(void);
258 void xloadcols(void);
259 diff --git a/x.c b/x.c
260 index 9b29264..af93cad 100644
261 --- a/x.c
262 +++ b/x.c
263 @@ -19,6 +19,7 @@ char *argv0;
264 #include "arg.h"
265 #include "st.h"
266 #include "win.h"
267 +#include "hb.h"
268
269 /* types used in config.h */
270 typedef struct {
271 @@ -1031,6 +1032,9 @@ xunloadfont(Font *f)
272 void
273 xunloadfonts(void)
274 {
275 + /* Clear Harfbuzz font cache. */
276 + hbunloadfonts();
277 +
278 /* Free the loaded fonts in the font cache. */
279 while (frclen > 0)
280 XftFontClose(xw.dpy, frc[--frclen].font);
281 @@ -1231,7 +1235,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const…
282 mode = glyphs[i].mode;
283
284 /* Skip dummy wide-character spacing. */
285 - if (mode == ATTR_WDUMMY)
286 + if (mode & ATTR_WDUMMY)
287 continue;
288
289 /* Determine font for glyph if different from previous …
290 @@ -1343,6 +1347,9 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const…
291 numspecs++;
292 }
293
294 + /* Harfbuzz transformation for ligatures. */
295 + hbtransform(specs, glyphs, len, x, y);
296 +
297 return numspecs;
298 }
299
300 @@ -1496,14 +1503,17 @@ xdrawglyph(Glyph g, int x, int y)
301 }
302
303 void
304 -xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og)
305 +xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line lin…
306 {
307 Color drawcol;
308
309 /* remove the old cursor */
310 if (selected(ox, oy))
311 og.mode ^= ATTR_REVERSE;
312 - xdrawglyph(og, ox, oy);
313 +
314 + /* Redraw the line where cursor was previously.
315 + * It will restore the ligatures broken by the cursor. */
316 + xdrawline(line, 0, oy, len);
317
318 if (IS_SET(MODE_HIDE))
319 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.