Introduction
Introduction Statistics Contact Development Disclaimer Help
st-ligatures-boxdraw-20200430-0.8.3.diff - sites - public wiki contents of suck…
git clone git://git.suckless.org/sites
Log
Files
Refs
---
st-ligatures-boxdraw-20200430-0.8.3.diff (7975B)
---
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 beafc35..3df5c83 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..467bcac
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..b3e02d0
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 c035e19..13cbcf7 100644
204 --- a/st.c
205 +++ b/st.c
206 @@ -2602,7 +2602,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;
214 term.ocy = term.c.y;
215 xfinishdraw();
216 diff --git a/st.h b/st.h
217 index a6c382a..c7e79c6 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 @@ -34,6 +35,7 @@ enum glyph_attribute {
231 ATTR_WIDE = 1 << 9,
232 ATTR_WDUMMY = 1 << 10,
233 ATTR_BOXDRAW = 1 << 11,
234 + ATTR_LIGA = 1 << 12,
235 ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
236 };
237
238 diff --git a/win.h b/win.h
239 index a6ef1b9..bc0d180 100644
240 --- a/win.h
241 +++ b/win.h
242 @@ -25,7 +25,7 @@ enum win_mode {
243
244 void xbell(void);
245 void xclipcopy(void);
246 -void xdrawcursor(int, int, Glyph, int, int, Glyph);
247 +void xdrawcursor(int, int, Glyph, int, int, Glyph, Line, int);
248 void xdrawline(Line, int, int, int);
249 void xfinishdraw(void);
250 void xloadcols(void);
251 diff --git a/x.c b/x.c
252 index 6f7ea2c..a79384c 100644
253 --- a/x.c
254 +++ b/x.c
255 @@ -19,6 +19,7 @@ char *argv0;
256 #include "arg.h"
257 #include "st.h"
258 #include "win.h"
259 +#include "hb.h"
260
261 /* types used in config.h */
262 typedef struct {
263 @@ -1031,6 +1032,9 @@ xunloadfont(Font *f)
264 void
265 xunloadfonts(void)
266 {
267 + /* Clear Harfbuzz font cache. */
268 + hbunloadfonts();
269 +
270 /* Free the loaded fonts in the font cache. */
271 while (frclen > 0)
272 XftFontClose(xw.dpy, frc[--frclen].font);
273 @@ -1231,7 +1235,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const…
274 mode = glyphs[i].mode;
275
276 /* Skip dummy wide-character spacing. */
277 - if (mode == ATTR_WDUMMY)
278 + if (mode & ATTR_WDUMMY)
279 continue;
280
281 /* Determine font for glyph if different from previous …
282 @@ -1343,6 +1347,9 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const…
283 numspecs++;
284 }
285
286 + /* Harfbuzz transformation for ligatures. */
287 + hbtransform(specs, glyphs, len, x, y);
288 +
289 return numspecs;
290 }
291
292 @@ -1496,14 +1503,17 @@ xdrawglyph(Glyph g, int x, int y)
293 }
294
295 void
296 -xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og)
297 +xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line lin…
298 {
299 Color drawcol;
300
301 /* remove the old cursor */
302 if (selected(ox, oy))
303 og.mode ^= ATTR_REVERSE;
304 - xdrawglyph(og, ox, oy);
305 +
306 + /* Redraw the line where cursor was previously.
307 + * It will restore the ligatures broken by the cursor. */
308 + xdrawline(line, 0, oy, len);
309
310 if (IS_SET(MODE_HIDE))
311 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.