st-ligatures-boxdraw-20241226-0.9.2.diff - sites - public wiki contents of suck… | |
git clone git://git.suckless.org/sites | |
Log | |
Files | |
Refs | |
--- | |
st-ligatures-boxdraw-20241226-0.9.2.diff (19317B) | |
--- | |
1 diff --git a/Makefile b/Makefile | |
2 index a64b4c2..05124bf 100644 | |
3 --- a/Makefile | |
4 +++ b/Makefile | |
5 @@ -3,9 +3,9 @@ | |
6 .POSIX: | |
7 | |
8 include config.mk | |
9 | |
10 -SRC = st.c x.c boxdraw.c | |
11 +SRC = st.c x.c boxdraw.c hb.c | |
12 OBJ = $(SRC:.c=.o) | |
13 | |
14 all: st | |
15 | |
16 @@ -15,10 +15,11 @@ config.h: | |
17 .c.o: | |
18 $(CC) $(STCFLAGS) -c $< | |
19 | |
20 st.o: config.h st.h win.h | |
21 -x.o: arg.h config.h st.h win.h | |
22 +x.o: arg.h config.h st.h win.h hb.h | |
23 boxdraw.o: config.h st.h boxdraw_data.h | |
24 +hb.o: st.h | |
25 | |
26 $(OBJ): config.h config.mk | |
27 | |
28 st: $(OBJ) | |
29 diff --git a/config.mk b/config.mk | |
30 index fdc29a7..6833b3b 100644 | |
31 --- a/config.mk | |
32 +++ b/config.mk | |
33 @@ -14,12 +14,14 @@ PKG_CONFIG = pkg-config | |
34 | |
35 # includes and libs | |
36 INCS = -I$(X11INC) \ | |
37 `$(PKG_CONFIG) --cflags fontconfig` \ | |
38 - `$(PKG_CONFIG) --cflags freetype2` | |
39 + `$(PKG_CONFIG) --cflags freetype2` \ | |
40 + `$(PKG_CONFIG) --cflags harfbuzz` | |
41 LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft \ | |
42 `$(PKG_CONFIG) --libs fontconfig` \ | |
43 - `$(PKG_CONFIG) --libs freetype2` | |
44 + `$(PKG_CONFIG) --libs freetype2` \ | |
45 + `$(PKG_CONFIG) --libs harfbuzz` | |
46 | |
47 # flags | |
48 STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 | |
49 STCFLAGS = $(INCS) $(STCPPFLAGS) $(CPPFLAGS) $(CFLAGS) | |
50 @@ -28,9 +30,10 @@ STLDFLAGS = $(LIBS) $(LDFLAGS) | |
51 # OpenBSD: | |
52 #CPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 -D_BSD_SOURCE | |
53 #LIBS = -L$(X11LIB) -lm -lX11 -lutil -lXft \ | |
54 # `$(PKG_CONFIG) --libs fontconfig` \ | |
55 -# `$(PKG_CONFIG) --libs freetype2` | |
56 +# `$(PKG_CONFIG) --libs freetype2` \ | |
57 +# `$(PKG_CONFIG) --libs harfbuzz` | |
58 #MANPREFIX = ${PREFIX}/man | |
59 | |
60 # compiler and linker | |
61 # CC = c99 | |
62 diff --git a/hb.c b/hb.c | |
63 new file mode 100644 | |
64 index 0000000..99412c8 | |
65 --- /dev/null | |
66 +++ b/hb.c | |
67 @@ -0,0 +1,125 @@ | |
68 +#include <stdlib.h> | |
69 +#include <stdio.h> | |
70 +#include <math.h> | |
71 +#include <X11/Xft/Xft.h> | |
72 +#include <X11/cursorfont.h> | |
73 +#include <hb.h> | |
74 +#include <hb-ft.h> | |
75 + | |
76 +#include "st.h" | |
77 +#include "hb.h" | |
78 + | |
79 +#define FEATURE(c1,c2,c3,c4) { .tag = HB_TAG(c1,c2,c3,c4), .value = 1, … | |
80 +#define BUFFER_STEP 256 | |
81 + | |
82 +hb_font_t *hbfindfont(XftFont *match); | |
83 + | |
84 +typedef struct { | |
85 + XftFont *match; | |
86 + hb_font_t *font; | |
87 +} HbFontMatch; | |
88 + | |
89 +typedef struct { | |
90 + size_t capacity; | |
91 + HbFontMatch *fonts; | |
92 +} HbFontCache; | |
93 + | |
94 +static HbFontCache hbfontcache = { 0, NULL }; | |
95 + | |
96 +typedef struct { | |
97 + size_t capacity; | |
98 + Rune *runes; | |
99 +} RuneBuffer; | |
100 + | |
101 +static RuneBuffer hbrunebuffer = { 0, NULL }; | |
102 + | |
103 +/* | |
104 + * Poplulate the array with a list of font features, wrapped in FEATURE… | |
105 + * e. g. | |
106 + * FEATURE('c', 'a', 'l', 't'), FEATURE('d', 'l', 'i', 'g') | |
107 + */ | |
108 +hb_feature_t features[] = { }; | |
109 + | |
110 +void | |
111 +hbunloadfonts() | |
112 +{ | |
113 + for (int i = 0; i < hbfontcache.capacity; i++) { | |
114 + hb_font_destroy(hbfontcache.fonts[i].font); | |
115 + XftUnlockFace(hbfontcache.fonts[i].match); | |
116 + } | |
117 + | |
118 + if (hbfontcache.fonts != NULL) { | |
119 + free(hbfontcache.fonts); | |
120 + hbfontcache.fonts = NULL; | |
121 + } | |
122 + hbfontcache.capacity = 0; | |
123 +} | |
124 + | |
125 +hb_font_t * | |
126 +hbfindfont(XftFont *match) | |
127 +{ | |
128 + for (int i = 0; i < hbfontcache.capacity; i++) { | |
129 + if (hbfontcache.fonts[i].match == match) | |
130 + return hbfontcache.fonts[i].font; | |
131 + } | |
132 + | |
133 + /* Font not found in cache, caching it now. */ | |
134 + hbfontcache.fonts = realloc(hbfontcache.fonts, sizeof(HbFontMat… | |
135 + FT_Face face = XftLockFace(match); | |
136 + hb_font_t *font = hb_ft_font_create(face, NULL); | |
137 + if (font == NULL) | |
138 + die("Failed to load Harfbuzz font."); | |
139 + | |
140 + hbfontcache.fonts[hbfontcache.capacity].match = match; | |
141 + hbfontcache.fonts[hbfontcache.capacity].font = font; | |
142 + hbfontcache.capacity += 1; | |
143 + | |
144 + return font; | |
145 +} | |
146 + | |
147 +void hbtransform(HbTransformData *data, XftFont *xfont, const Glyph *gl… | |
148 + ushort mode = USHRT_MAX; | |
149 + unsigned int glyph_count; | |
150 + int rune_idx, glyph_idx, end = start + length; | |
151 + | |
152 + hb_font_t *font = hbfindfont(xfont); | |
153 + if (font == NULL) | |
154 + return; | |
155 + | |
156 + hb_buffer_t *buffer = hb_buffer_create(); | |
157 + hb_buffer_set_direction(buffer, HB_DIRECTION_LTR); | |
158 + hb_buffer_set_cluster_level(buffer, HB_BUFFER_CLUSTER_LEVEL_MON… | |
159 + | |
160 + /* Resize the buffer if required length is larger. */ | |
161 + if (hbrunebuffer.capacity < length) { | |
162 + hbrunebuffer.capacity = (length / BUFFER_STEP + 1) * BU… | |
163 + hbrunebuffer.runes = realloc(hbrunebuffer.runes, hbrune… | |
164 + } | |
165 + | |
166 + /* Fill buffer with codepoints. */ | |
167 + for (rune_idx = 0, glyph_idx = start; glyph_idx < end; glyph_id… | |
168 + hbrunebuffer.runes[rune_idx] = glyphs[glyph_idx].u; | |
169 + mode = glyphs[glyph_idx].mode; | |
170 + if (mode & ATTR_WDUMMY) | |
171 + hbrunebuffer.runes[rune_idx] = 0x0020; | |
172 + } | |
173 + hb_buffer_add_codepoints(buffer, hbrunebuffer.runes, length, 0,… | |
174 + | |
175 + /* Shape the segment. */ | |
176 + hb_shape(font, buffer, features, sizeof(features)/sizeof(hb_fea… | |
177 + | |
178 + /* Get new glyph info. */ | |
179 + hb_glyph_info_t *info = hb_buffer_get_glyph_infos(buffer, &glyp… | |
180 + hb_glyph_position_t *pos = hb_buffer_get_glyph_positions(buffer… | |
181 + | |
182 + /* Fill the output. */ | |
183 + data->buffer = buffer; | |
184 + data->glyphs = info; | |
185 + data->positions = pos; | |
186 + data->count = glyph_count; | |
187 +} | |
188 + | |
189 +void hbcleanup(HbTransformData *data) { | |
190 + hb_buffer_destroy(data->buffer); | |
191 + memset(data, 0, sizeof(HbTransformData)); | |
192 +} | |
193 diff --git a/hb.h b/hb.h | |
194 new file mode 100644 | |
195 index 0000000..3b0ef44 | |
196 --- /dev/null | |
197 +++ b/hb.h | |
198 @@ -0,0 +1,14 @@ | |
199 +#include <X11/Xft/Xft.h> | |
200 +#include <hb.h> | |
201 +#include <hb-ft.h> | |
202 + | |
203 +typedef struct { | |
204 + hb_buffer_t *buffer; | |
205 + hb_glyph_info_t *glyphs; | |
206 + hb_glyph_position_t *positions; | |
207 + unsigned int count; | |
208 +} HbTransformData; | |
209 + | |
210 +void hbunloadfonts(); | |
211 +void hbtransform(HbTransformData *, XftFont *, const Glyph *, int, int); | |
212 +void hbcleanup(HbTransformData *); | |
213 diff --git a/st.c b/st.c | |
214 index ec6fbf3..1385f77 100644 | |
215 --- a/st.c | |
216 +++ b/st.c | |
217 @@ -2661,9 +2661,10 @@ draw(void) | |
218 cx--; | |
219 | |
220 drawregion(0, 0, term.col, term.row); | |
221 xdrawcursor(cx, term.c.y, term.line[term.c.y][cx], | |
222 - term.ocx, term.ocy, term.line[term.ocy][term.oc… | |
223 + term.ocx, term.ocy, term.line[term.ocy][term.oc… | |
224 + term.line[term.ocy], term.col); | |
225 term.ocx = cx; | |
226 term.ocy = term.c.y; | |
227 xfinishdraw(); | |
228 if (ocx != term.ocx || ocy != term.ocy) | |
229 diff --git a/st.h b/st.h | |
230 index 808f5f7..ae41368 100644 | |
231 --- a/st.h | |
232 +++ b/st.h | |
233 @@ -10,9 +10,10 @@ | |
234 #define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b)) | |
235 #define DIVCEIL(n, d) (((n) + ((d) - 1)) / (d)) | |
236 #define DEFAULT(a, b) (a) = (a) ? (a) : (b) | |
237 #define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b)… | |
238 -#define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg !=… | |
239 +#define ATTRCMP(a, b) (((a).mode & (~ATTR_WRAP)) != ((b)… | |
240 + (a).fg != (b).fg || \ | |
241 (a).bg != (b).bg) | |
242 #define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + \ | |
243 (t1.tv_nsec-t2.tv_nsec)/1E6) | |
244 #define MODBIT(x, set, bit) ((set) ? ((x) |= (bit)) : ((x) &= ~(… | |
245 diff --git a/win.h b/win.h | |
246 index 6de960d..94679e4 100644 | |
247 --- a/win.h | |
248 +++ b/win.h | |
249 @@ -24,9 +24,9 @@ enum win_mode { | |
250 }; | |
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 int xsetcolorname(int, const char *); | |
260 diff --git a/x.c b/x.c | |
261 index 978a8fc..c2d9993 100644 | |
262 --- a/x.c | |
263 +++ b/x.c | |
264 @@ -18,8 +18,9 @@ | |
265 char *argv0; | |
266 #include "arg.h" | |
267 #include "st.h" | |
268 #include "win.h" | |
269 +#include "hb.h" | |
270 | |
271 /* types used in config.h */ | |
272 typedef struct { | |
273 uint mod; | |
274 @@ -140,10 +141,11 @@ typedef struct { | |
275 GC gc; | |
276 } DC; | |
277 | |
278 static inline ushort sixd_to_16bit(int); | |
279 +static void xresetfontsettings(ushort mode, Font **font, int *frcflags); | |
280 static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, … | |
281 -static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, i… | |
282 +static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, i… | |
283 static void xdrawglyph(Glyph, int, int); | |
284 static void xclear(int, int, int, int); | |
285 static int xgeommasktogravity(int); | |
286 static int ximopen(Display *); | |
287 @@ -756,9 +758,9 @@ xresize(int col, int row) | |
288 XftDrawChange(xw.draw, xw.buf); | |
289 xclear(0, 0, win.w, win.h); | |
290 | |
291 /* resize to new width */ | |
292 - xw.specbuf = xrealloc(xw.specbuf, col * sizeof(GlyphFontSpec)); | |
293 + xw.specbuf = xrealloc(xw.specbuf, col * sizeof(GlyphFontSpec) *… | |
294 } | |
295 | |
296 ushort | |
297 sixd_to_16bit(int x) | |
298 @@ -1061,8 +1063,11 @@ xunloadfont(Font *f) | |
299 | |
300 void | |
301 xunloadfonts(void) | |
302 { | |
303 + /* Clear Harfbuzz font cache. */ | |
304 + hbunloadfonts(); | |
305 + | |
306 /* Free the loaded fonts in the font cache. */ | |
307 while (frclen > 0) | |
308 XftFontClose(xw.dpy, frc[--frclen].font); | |
309 | |
310 @@ -1184,9 +1189,9 @@ xinit(int cols, int rows) | |
311 XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); | |
312 XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); | |
313 | |
314 /* font spec buffer */ | |
315 - xw.specbuf = xmalloc(cols * sizeof(GlyphFontSpec)); | |
316 + xw.specbuf = xmalloc(cols * sizeof(GlyphFontSpec) * 4); | |
317 | |
318 /* Xft rendering context */ | |
319 xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap); | |
320 | |
321 @@ -1240,149 +1245,162 @@ xinit(int cols, int rows) | |
322 | |
323 boxdraw_xinit(xw.dpy, xw.cmap, xw.draw, xw.vis); | |
324 } | |
325 | |
326 +void | |
327 +xresetfontsettings(ushort mode, Font **font, int *frcflags) | |
328 +{ | |
329 + *font = &dc.font; | |
330 + if ((mode & ATTR_ITALIC) && (mode & ATTR_BOLD)) { | |
331 + *font = &dc.ibfont; | |
332 + *frcflags = FRC_ITALICBOLD; | |
333 + } else if (mode & ATTR_ITALIC) { | |
334 + *font = &dc.ifont; | |
335 + *frcflags = FRC_ITALIC; | |
336 + } else if (mode & ATTR_BOLD) { | |
337 + *font = &dc.bfont; | |
338 + *frcflags = FRC_BOLD; | |
339 + } | |
340 +} | |
341 + | |
342 int | |
343 xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int l… | |
344 { | |
345 float winx = borderpx + x * win.cw, winy = borderpx + y * win.c… | |
346 - ushort mode, prevmode = USHRT_MAX; | |
347 + ushort mode = glyphs[0].mode & ~ATTR_WRAP; | |
348 Font *font = &dc.font; | |
349 int frcflags = FRC_NORMAL; | |
350 - float runewidth = win.cw; | |
351 + float runewidth = win.cw * ((glyphs[0].mode & ATTR_WIDE) ? 2.0f… | |
352 Rune rune; | |
353 FT_UInt glyphidx; | |
354 FcResult fcres; | |
355 FcPattern *fcpattern, *fontpattern; | |
356 FcFontSet *fcsets[] = { NULL }; | |
357 FcCharSet *fccharset; | |
358 - int i, f, numspecs = 0; | |
359 + int f, code_idx, numspecs = 0; | |
360 + float cluster_xp = xp, cluster_yp = yp; | |
361 + HbTransformData shaped = { 0 }; | |
362 | |
363 - for (i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) { | |
364 - /* Fetch rune and mode for current glyph. */ | |
365 - rune = glyphs[i].u; | |
366 - mode = glyphs[i].mode; | |
367 + /* Initial values. */ | |
368 + xresetfontsettings(mode, &font, &frcflags); | |
369 | |
370 - /* Skip dummy wide-character spacing. */ | |
371 - if (mode == ATTR_WDUMMY) | |
372 + /* Shape the segment. */ | |
373 + hbtransform(&shaped, font->match, glyphs, 0, len); | |
374 + xp = winx; yp = winy + font->ascent; | |
375 + cluster_xp = xp; cluster_yp = yp; | |
376 + | |
377 + for (code_idx = 0; code_idx < shaped.count; code_idx++) { | |
378 + int idx = shaped.glyphs[code_idx].cluster; | |
379 + | |
380 + if (glyphs[idx].mode & ATTR_WDUMMY) | |
381 continue; | |
382 | |
383 - /* Determine font for glyph if different from previous … | |
384 - if (prevmode != mode) { | |
385 - prevmode = mode; | |
386 - font = &dc.font; | |
387 - frcflags = FRC_NORMAL; | |
388 - runewidth = win.cw * ((mode & ATTR_WIDE) ? 2.0f… | |
389 - if ((mode & ATTR_ITALIC) && (mode & ATTR_BOLD))… | |
390 - font = &dc.ibfont; | |
391 - frcflags = FRC_ITALICBOLD; | |
392 - } else if (mode & ATTR_ITALIC) { | |
393 - font = &dc.ifont; | |
394 - frcflags = FRC_ITALIC; | |
395 - } else if (mode & ATTR_BOLD) { | |
396 - font = &dc.bfont; | |
397 - frcflags = FRC_BOLD; | |
398 - } | |
399 - yp = winy + font->ascent; | |
400 + /* Advance the drawing cursor if we've moved to a new c… | |
401 + if (code_idx > 0 && idx != shaped.glyphs[code_idx - 1].… | |
402 + xp += runewidth; | |
403 + cluster_xp = xp; | |
404 + cluster_yp = yp; | |
405 } | |
406 | |
407 - if (mode & ATTR_BOXDRAW) { | |
408 + if (glyphs[idx].mode & ATTR_BOXDRAW) { | |
409 /* minor shoehorning: boxdraw uses only this us… | |
410 - glyphidx = boxdrawindex(&glyphs[i]); | |
411 - } else { | |
412 - /* Lookup character index with default font. */ | |
413 - glyphidx = XftCharIndex(xw.dpy, font->match, ru… | |
414 - } | |
415 - if (glyphidx) { | |
416 specs[numspecs].font = font->match; | |
417 - specs[numspecs].glyph = glyphidx; | |
418 - specs[numspecs].x = (short)xp; | |
419 - specs[numspecs].y = (short)yp; | |
420 - xp += runewidth; | |
421 + specs[numspecs].glyph = boxdrawindex(&glyphs[id… | |
422 + specs[numspecs].x = xp; | |
423 + specs[numspecs].y = yp; | |
424 numspecs++; | |
425 - continue; | |
426 - } | |
427 - | |
428 - /* Fallback on font cache, search the font cache for ma… | |
429 - for (f = 0; f < frclen; f++) { | |
430 - glyphidx = XftCharIndex(xw.dpy, frc[f].font, ru… | |
431 - /* Everything correct. */ | |
432 - if (glyphidx && frc[f].flags == frcflags) | |
433 - break; | |
434 - /* We got a default font for a not found glyph.… | |
435 - if (!glyphidx && frc[f].flags == frcflags | |
436 - && frc[f].unicodep == rune) { | |
437 - break; | |
438 + } else if (shaped.glyphs[code_idx].codepoint != 0) { | |
439 + /* If symbol is found, put it into the specs. */ | |
440 + specs[numspecs].font = font->match; | |
441 + specs[numspecs].glyph = shaped.glyphs[code_idx]… | |
442 + specs[numspecs].x = cluster_xp + (short)(shaped… | |
443 + specs[numspecs].y = cluster_yp - (short)(shaped… | |
444 + cluster_xp += shaped.positions[code_idx].x_adva… | |
445 + cluster_yp += shaped.positions[code_idx].y_adva… | |
446 + numspecs++; | |
447 + } else { | |
448 + /* If it's not found, try to fetch it through t… | |
449 + rune = glyphs[idx].u; | |
450 + for (f = 0; f < frclen; f++) { | |
451 + glyphidx = XftCharIndex(xw.dpy, frc[f].… | |
452 + /* Everything correct. */ | |
453 + if (glyphidx && frc[f].flags == frcflag… | |
454 + break; | |
455 + /* We got a default font for a not foun… | |
456 + if (!glyphidx && frc[f].flags == frcfla… | |
457 + && frc[f].unicodep == r… | |
458 + break; | |
459 + } | |
460 } | |
461 - } | |
462 - | |
463 - /* Nothing was found. Use fontconfig to find matching f… | |
464 - if (f >= frclen) { | |
465 - if (!font->set) | |
466 - font->set = FcFontSort(0, font->pattern, | |
467 - 1, 0, &fcres); | |
468 - fcsets[0] = font->set; | |
469 - | |
470 - /* | |
471 - * Nothing was found in the cache. Now use | |
472 - * some dozen of Fontconfig calls to get the | |
473 - * font for one single character. | |
474 - * | |
475 - * Xft and fontconfig are design failures. | |
476 - */ | |
477 - fcpattern = FcPatternDuplicate(font->pattern); | |
478 - fccharset = FcCharSetCreate(); | |
479 - | |
480 - FcCharSetAddChar(fccharset, rune); | |
481 - FcPatternAddCharSet(fcpattern, FC_CHARSET, | |
482 - fccharset); | |
483 - FcPatternAddBool(fcpattern, FC_SCALABLE, 1); | |
484 - | |
485 - FcConfigSubstitute(0, fcpattern, | |
486 - FcMatchPattern); | |
487 - FcDefaultSubstitute(fcpattern); | |
488 | |
489 - fontpattern = FcFontSetMatch(0, fcsets, 1, | |
490 - fcpattern, &fcres); | |
491 - | |
492 - /* Allocate memory for the new cache entry. */ | |
493 - if (frclen >= frccap) { | |
494 - frccap += 16; | |
495 - frc = xrealloc(frc, frccap * sizeof(Fon… | |
496 + /* Nothing was found. Use fontconfig to find ma… | |
497 + if (f >= frclen) { | |
498 + if (!font->set) | |
499 + font->set = FcFontSort(0, font-… | |
500 + 1, 0, &f… | |
501 + fcsets[0] = font->set; | |
502 + | |
503 + /* | |
504 + * Nothing was found in the cache. Now … | |
505 + * some dozen of Fontconfig calls to ge… | |
506 + * font for one single character. | |
507 + * | |
508 + * Xft and fontconfig are design failur… | |
509 + */ | |
510 + fcpattern = FcPatternDuplicate(font->pa… | |
511 + fccharset = FcCharSetCreate(); | |
512 + | |
513 + FcCharSetAddChar(fccharset, rune); | |
514 + FcPatternAddCharSet(fcpattern, FC_CHARS… | |
515 + fccharset); | |
516 + FcPatternAddBool(fcpattern, FC_SCALABLE… | |
517 + | |
518 + FcConfigSubstitute(0, fcpattern, | |
519 + FcMatchPattern); | |
520 + FcDefaultSubstitute(fcpattern); | |
521 + | |
522 + fontpattern = FcFontSetMatch(0, fcsets,… | |
523 + fcpattern, &fcres); | |
524 + | |
525 + /* Allocate memory for the new cache en… | |
526 + if (frclen >= frccap) { | |
527 + frccap += 16; | |
528 + frc = xrealloc(frc, frccap * si… | |
529 + } | |
530 + | |
531 + frc[frclen].font = XftFontOpenPattern(x… | |
532 + fontpattern); | |
533 + if (!frc[frclen].font) | |
534 + die("XftFontOpenPattern failed … | |
535 + strerror(errno)); | |
536 + frc[frclen].flags = frcflags; | |
537 + frc[frclen].unicodep = rune; | |
538 + | |
539 + glyphidx = XftCharIndex(xw.dpy, frc[frc… | |
540 + | |
541 + f = frclen; | |
542 + frclen++; | |
543 + | |
544 + FcPatternDestroy(fcpattern); | |
545 + FcCharSetDestroy(fccharset); | |
546 } | |
547 | |
548 - frc[frclen].font = XftFontOpenPattern(xw.dpy, | |
549 - fontpattern); | |
550 - if (!frc[frclen].font) | |
551 - die("XftFontOpenPattern failed seeking … | |
552 - strerror(errno)); | |
553 - frc[frclen].flags = frcflags; | |
554 - frc[frclen].unicodep = rune; | |
555 - | |
556 - glyphidx = XftCharIndex(xw.dpy, frc[frclen].fon… | |
557 - | |
558 - f = frclen; | |
559 - frclen++; | |
560 - | |
561 - FcPatternDestroy(fcpattern); | |
562 - FcCharSetDestroy(fccharset); | |
563 + specs[numspecs].font = frc[f].font; | |
564 + specs[numspecs].glyph = glyphidx; | |
565 + specs[numspecs].x = (short)xp; | |
566 + specs[numspecs].y = (short)yp; | |
567 + numspecs++; | |
568 } | |
569 - | |
570 - specs[numspecs].font = frc[f].font; | |
571 - specs[numspecs].glyph = glyphidx; | |
572 - specs[numspecs].x = (short)xp; | |
573 - specs[numspecs].y = (short)yp; | |
574 - xp += runewidth; | |
575 - numspecs++; | |
576 } | |
577 | |
578 + /* Cleanup and get ready for next segment. */ | |
579 + hbcleanup(&shaped); | |
580 return numspecs; | |
581 } | |
582 | |
583 void | |
584 -xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len,… | |
585 +xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len,… | |
586 { | |
587 - int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1); | |
588 int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, | |
589 width = charlen * win.cw; | |
590 Color *fg, *bg, *temp, revfg, revbg, truefg, truebg; | |
591 XRenderColor colfg, colbg; | |
592 @@ -1520,23 +1538,26 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *spec… | |
593 void | |
594 xdrawglyph(Glyph g, int x, int y) | |
595 { | |
596 int numspecs; | |
597 - XftGlyphFontSpec spec; | |
598 + XftGlyphFontSpec *specs = xw.specbuf; | |
599 | |
600 - numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y); | |
601 - xdrawglyphfontspecs(&spec, g, numspecs, x, y); | |
602 + numspecs = xmakeglyphfontspecs(specs, &g, 1, x, y); | |
603 + xdrawglyphfontspecs(specs, g, numspecs, x, y, (g.mode & ATTR_WI… | |
604 } | |
605 | |
606 void | |
607 -xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) | |
608 +xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line lin… | |
609 { | |
610 Color drawcol; | |
611 | |
612 /* remove the old cursor */ | |
613 if (selected(ox, oy)) | |
614 og.mode ^= ATTR_REVERSE; | |
615 - xdrawglyph(og, ox, oy); | |
616 + | |
617 + /* Redraw the line where cursor was previously. | |
618 + * It will restore the ligatures broken by the cursor. */ | |
619 + xdrawline(line, 0, oy, len); | |
620 | |
621 if (IS_SET(MODE_HIDE)) | |
622 return; | |
623 | |
624 @@ -1668,30 +1689,30 @@ xdrawline(Line line, int x1, int y1, int x2) | |
625 int i, x, ox, numspecs; | |
626 Glyph base, new; | |
627 XftGlyphFontSpec *specs = xw.specbuf; | |
628 | |
629 - numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y… | |
630 i = ox = 0; | |
631 - for (x = x1; x < x2 && i < numspecs; x++) { | |
632 + for (x = x1; x < x2; x++) { | |
633 new = line[x]; | |
634 if (new.mode == ATTR_WDUMMY) | |
635 continue; | |
636 if (selected(x, y1)) | |
637 new.mode ^= ATTR_REVERSE; | |
638 - if (i > 0 && ATTRCMP(base, new)) { | |
639 - xdrawglyphfontspecs(specs, base, i, ox, y1); | |
640 - specs += i; | |
641 - numspecs -= i; | |
642 + if ((i > 0) && ATTRCMP(base, new)) { | |
643 + numspecs = xmakeglyphfontspecs(specs, &line[ox]… | |
644 + xdrawglyphfontspecs(specs, base, numspecs, ox, … | |
645 i = 0; | |
646 } | |
647 if (i == 0) { | |
648 ox = x; | |
649 base = new; | |
650 } | |
651 i++; | |
652 } | |
653 - if (i > 0) | |
654 - xdrawglyphfontspecs(specs, base, i, ox, y1); | |
655 + if (i > 0) { | |
656 + numspecs = xmakeglyphfontspecs(specs, &line[ox], x2 - o… | |
657 + xdrawglyphfontspecs(specs, base, numspecs, ox, y1, x2 -… | |
658 + } | |
659 } | |
660 | |
661 void | |
662 xfinishdraw(void) |