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