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