Introduction
Introduction Statistics Contact Development Disclaimer Help
st-ligatures-20200428-28ad288.diff - sites - public wiki contents of suckless.o…
git clone git://git.suckless.org/sites
Log
Files
Refs
---
st-ligatures-20200428-28ad288.diff (7878B)
---
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 0cbb002..a021b2c 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..7df2828
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..b3e02d0
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 3e48410..e5064d6 100644
200 --- a/st.c
201 +++ b/st.c
202 @@ -2585,7 +2585,8 @@ draw(void)
203
204 drawregion(0, 0, term.col, term.row);
205 xdrawcursor(cx, term.c.y, term.line[term.c.y][cx],
206 - term.ocx, term.ocy, term.line[term.ocy][term.oc…
207 + term.ocx, term.ocy, term.line[term.ocy][term.oc…
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 a1928ca..07ba678 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 4cf6b21..410994d 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 @@ -1031,6 +1032,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 @@ -1229,7 +1233,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 @@ -1336,6 +1340,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 @@ -1485,14 +1492,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.