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