Introduction
Introduction Statistics Contact Development Disclaimer Help
st-ligatures-alpha-scrollback-20240105-0.9.diff - sites - public wiki contents …
git clone git://git.suckless.org/sites
Log
Files
Refs
---
st-ligatures-alpha-scrollback-20240105-0.9.diff (18803B)
---
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..99412c8
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 79ee9ba..454771d 100644
197 --- a/st.c
198 +++ b/st.c
199 @@ -2711,7 +2711,9 @@ draw(void)
200 drawregion(0, 0, term.col, term.row);
201 if (term.scr == 0)
202 xdrawcursor(cx, term.c.y, term.line[term.c.y][cx],
203 - term.ocx, term.ocy, term.line[term.ocy]…
204 + term.ocx, term.ocy, term.line[term.ocy]…
205 + term.line[term.ocy], term.col);
206 +
207 term.ocx = cx;
208 term.ocy = term.c.y;
209 xfinishdraw();
210 diff --git a/st.h b/st.h
211 index 78762a2..01eea49 100644
212 --- a/st.h
213 +++ b/st.h
214 @@ -11,7 +11,8 @@
215 #define DIVCEIL(n, d) (((n) + ((d) - 1)) / (d))
216 #define DEFAULT(a, b) (a) = (a) ? (a) : (b)
217 #define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b)…
218 -#define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg !=…
219 +#define ATTRCMP(a, b) (((a).mode & (~ATTR_WRAP)) != ((b)…
220 + (a).fg != (b).fg || \
221 (a).bg != (b).bg)
222 #define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + \
223 (t1.tv_nsec-t2.tv_nsec)/1E6)
224 diff --git a/win.h b/win.h
225 index 6de960d..94679e4 100644
226 --- a/win.h
227 +++ b/win.h
228 @@ -25,7 +25,7 @@ enum win_mode {
229
230 void xbell(void);
231 void xclipcopy(void);
232 -void xdrawcursor(int, int, Glyph, int, int, Glyph);
233 +void xdrawcursor(int, int, Glyph, int, int, Glyph, Line, int);
234 void xdrawline(Line, int, int, int);
235 void xfinishdraw(void);
236 void xloadcols(void);
237 diff --git a/x.c b/x.c
238 index 27e81d1..5e11c1f 100644
239 --- a/x.c
240 +++ b/x.c
241 @@ -19,6 +19,7 @@ char *argv0;
242 #include "arg.h"
243 #include "st.h"
244 #include "win.h"
245 +#include "hb.h"
246
247 /* types used in config.h */
248 typedef struct {
249 @@ -142,8 +143,9 @@ typedef struct {
250 } DC;
251
252 static inline ushort sixd_to_16bit(int);
253 +static void xresetfontsettings(ushort mode, Font **font, int *frcflags);
254 static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, …
255 -static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, i…
256 +static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, i…
257 static void xdrawglyph(Glyph, int, int);
258 static void xclear(int, int, int, int);
259 static int xgeommasktogravity(int);
260 @@ -759,7 +761,7 @@ xresize(int col, int row)
261 xclear(0, 0, win.w, win.h);
262
263 /* resize to new width */
264 - xw.specbuf = xrealloc(xw.specbuf, col * sizeof(GlyphFontSpec));
265 + xw.specbuf = xrealloc(xw.specbuf, col * sizeof(GlyphFontSpec) *…
266 }
267
268 ushort
269 @@ -1071,6 +1073,9 @@ xunloadfont(Font *f)
270 void
271 xunloadfonts(void)
272 {
273 + /* Clear Harfbuzz font cache. */
274 + hbunloadfonts();
275 +
276 /* Free the loaded fonts in the font cache. */
277 while (frclen > 0)
278 XftFontClose(xw.dpy, frc[--frclen].font);
279 @@ -1202,7 +1207,7 @@ xinit(int cols, int rows)
280 XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h);
281
282 /* font spec buffer */
283 - xw.specbuf = xmalloc(cols * sizeof(GlyphFontSpec));
284 + xw.specbuf = xmalloc(cols * sizeof(GlyphFontSpec) * 4);
285
286 /* Xft rendering context */
287 xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap);
288 @@ -1256,6 +1261,22 @@ xinit(int cols, int rows)
289 xsel.xtarget = XA_STRING;
290 }
291
292 +void
293 +xresetfontsettings(ushort mode, Font **font, int *frcflags)
294 +{
295 + *font = &dc.font;
296 + if ((mode & ATTR_ITALIC) && (mode & ATTR_BOLD)) {
297 + *font = &dc.ibfont;
298 + *frcflags = FRC_ITALICBOLD;
299 + } else if (mode & ATTR_ITALIC) {
300 + *font = &dc.ifont;
301 + *frcflags = FRC_ITALIC;
302 + } else if (mode & ATTR_BOLD) {
303 + *font = &dc.bfont;
304 + *frcflags = FRC_BOLD;
305 + }
306 +}
307 +
308 int
309 xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int l…
310 {
311 @@ -1270,128 +1291,156 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, c…
312 FcPattern *fcpattern, *fontpattern;
313 FcFontSet *fcsets[] = { NULL };
314 FcCharSet *fccharset;
315 - int i, f, numspecs = 0;
316 + int i, f, length = 0, start = 0, numspecs = 0;
317 + float cluster_xp = xp, cluster_yp = yp;
318 + HbTransformData shaped = { 0 };
319 +
320 + /* Initial values. */
321 + mode = prevmode = glyphs[0].mode & ~ATTR_WRAP;
322 + xresetfontsettings(mode, &font, &frcflags);
323
324 for (i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) {
325 - /* Fetch rune and mode for current glyph. */
326 - rune = glyphs[i].u;
327 - mode = glyphs[i].mode;
328 + mode = glyphs[i].mode & ~ATTR_WRAP;
329
330 /* Skip dummy wide-character spacing. */
331 - if (mode == ATTR_WDUMMY)
332 + if (mode & ATTR_WDUMMY && i < (len - 1))
333 continue;
334
335 - /* Determine font for glyph if different from previous …
336 - if (prevmode != mode) {
337 - prevmode = mode;
338 - font = &dc.font;
339 - frcflags = FRC_NORMAL;
340 - runewidth = win.cw * ((mode & ATTR_WIDE) ? 2.0f…
341 - if ((mode & ATTR_ITALIC) && (mode & ATTR_BOLD))…
342 - font = &dc.ibfont;
343 - frcflags = FRC_ITALICBOLD;
344 - } else if (mode & ATTR_ITALIC) {
345 - font = &dc.ifont;
346 - frcflags = FRC_ITALIC;
347 - } else if (mode & ATTR_BOLD) {
348 - font = &dc.bfont;
349 - frcflags = FRC_BOLD;
350 + if (
351 + prevmode != mode
352 + || ATTRCMP(glyphs[start], glyphs[i])
353 + || selected(x + i, y) != selected(x + start, y)
354 + || i == (len - 1)
355 + ) {
356 + /* Handle 1-character wide segments and end of …
357 + length = i - start;
358 + if (i == start) {
359 + length = 1;
360 + } else if (i == (len - 1)) {
361 + length = (i - start + 1);
362 }
363 - yp = winy + font->ascent;
364 - }
365
366 - /* Lookup character index with default font. */
367 - glyphidx = XftCharIndex(xw.dpy, font->match, rune);
368 - if (glyphidx) {
369 - specs[numspecs].font = font->match;
370 - specs[numspecs].glyph = glyphidx;
371 - specs[numspecs].x = (short)xp;
372 - specs[numspecs].y = (short)yp;
373 - xp += runewidth;
374 - numspecs++;
375 - continue;
376 - }
377 -
378 - /* Fallback on font cache, search the font cache for ma…
379 - for (f = 0; f < frclen; f++) {
380 - glyphidx = XftCharIndex(xw.dpy, frc[f].font, ru…
381 - /* Everything correct. */
382 - if (glyphidx && frc[f].flags == frcflags)
383 - break;
384 - /* We got a default font for a not found glyph.…
385 - if (!glyphidx && frc[f].flags == frcflags
386 - && frc[f].unicodep == rune) {
387 - break;
388 + /* Shape the segment. */
389 + hbtransform(&shaped, font->match, glyphs, start…
390 + runewidth = win.cw * ((glyphs[start].mode & ATT…
391 + cluster_xp = xp; cluster_yp = yp;
392 + for (int code_idx = 0; code_idx < shaped.count;…
393 + int idx = shaped.glyphs[code_idx].clust…
394 +
395 + if (glyphs[start + idx].mode & ATTR_WDU…
396 + continue;
397 +
398 + /* Advance the drawing cursor if we've …
399 + if (code_idx > 0 && idx != shaped.glyph…
400 + xp += runewidth;
401 + cluster_xp = xp;
402 + cluster_yp = yp;
403 + runewidth = win.cw * ((glyphs[s…
404 + }
405 +
406 + if (shaped.glyphs[code_idx].codepoint !…
407 + /* If symbol is found, put it i…
408 + specs[numspecs].font = font->ma…
409 + specs[numspecs].glyph = shaped.…
410 + specs[numspecs].x = cluster_xp …
411 + specs[numspecs].y = cluster_yp …
412 + cluster_xp += shaped.positions[…
413 + cluster_yp += shaped.positions[…
414 + numspecs++;
415 + } else {
416 + /* If it's not found, try to fe…
417 + rune = glyphs[start + idx].u;
418 + for (f = 0; f < frclen; f++) {
419 + glyphidx = XftCharIndex…
420 + /* Everything correct. …
421 + if (glyphidx && frc[f].…
422 + break;
423 + /* We got a default fon…
424 + if (!glyphidx && frc[f]…
425 + && frc[…
426 + break;
427 + }
428 + }
429 +
430 + /* Nothing was found. Use fontc…
431 + if (f >= frclen) {
432 + if (!font->set)
433 + font->set = FcF…
434 + …
435 + fcsets[0] = font->set;
436 +
437 + /*
438 + * Nothing was found in…
439 + * some dozen of Fontco…
440 + * font for one single …
441 + *
442 + * Xft and fontconfig a…
443 + */
444 + fcpattern = FcPatternDu…
445 + fccharset = FcCharSetCr…
446 +
447 + FcCharSetAddChar(fcchar…
448 + FcPatternAddCharSet(fcp…
449 + fcchars…
450 + FcPatternAddBool(fcpatt…
451 +
452 + FcConfigSubstitute(0, f…
453 + FcMatch…
454 + FcDefaultSubstitute(fcp…
455 +
456 + fontpattern = FcFontSet…
457 + fcpatte…
458 +
459 + /* Allocate memory for …
460 + if (frclen >= frccap) {
461 + frccap += 16;
462 + frc = xrealloc(…
463 + }
464 +
465 + frc[frclen].font = XftF…
466 + fontpat…
467 + if (!frc[frclen].font)
468 + die("XftFontOpe…
469 + strerro…
470 + frc[frclen].flags = frc…
471 + frc[frclen].unicodep = …
472 +
473 + glyphidx = XftCharIndex…
474 +
475 + f = frclen;
476 + frclen++;
477 +
478 + FcPatternDestroy(fcpatt…
479 + FcCharSetDestroy(fcchar…
480 + }
481 +
482 + specs[numspecs].font = frc[f].f…
483 + specs[numspecs].glyph = glyphid…
484 + specs[numspecs].x = (short)xp;
485 + specs[numspecs].y = (short)yp;
486 + numspecs++;
487 + }
488 }
489 - }
490
491 - /* Nothing was found. Use fontconfig to find matching f…
492 - if (f >= frclen) {
493 - if (!font->set)
494 - font->set = FcFontSort(0, font->pattern,
495 - 1, 0, &fcres);
496 - fcsets[0] = font->set;
497 + /* Cleanup and get ready for next segment. */
498 + hbcleanup(&shaped);
499 + start = i;
500
501 - /*
502 - * Nothing was found in the cache. Now use
503 - * some dozen of Fontconfig calls to get the
504 - * font for one single character.
505 - *
506 - * Xft and fontconfig are design failures.
507 - */
508 - fcpattern = FcPatternDuplicate(font->pattern);
509 - fccharset = FcCharSetCreate();
510 -
511 - FcCharSetAddChar(fccharset, rune);
512 - FcPatternAddCharSet(fcpattern, FC_CHARSET,
513 - fccharset);
514 - FcPatternAddBool(fcpattern, FC_SCALABLE, 1);
515 -
516 - FcConfigSubstitute(0, fcpattern,
517 - FcMatchPattern);
518 - FcDefaultSubstitute(fcpattern);
519 -
520 - fontpattern = FcFontSetMatch(0, fcsets, 1,
521 - fcpattern, &fcres);
522 -
523 - /* Allocate memory for the new cache entry. */
524 - if (frclen >= frccap) {
525 - frccap += 16;
526 - frc = xrealloc(frc, frccap * sizeof(Fon…
527 + /* Determine font for glyph if different from p…
528 + if (prevmode != mode) {
529 + prevmode = mode;
530 + xresetfontsettings(mode, &font, &frcfla…
531 + yp = winy + font->ascent;
532 }
533 -
534 - frc[frclen].font = XftFontOpenPattern(xw.dpy,
535 - fontpattern);
536 - if (!frc[frclen].font)
537 - die("XftFontOpenPattern failed seeking …
538 - strerror(errno));
539 - frc[frclen].flags = frcflags;
540 - frc[frclen].unicodep = rune;
541 -
542 - glyphidx = XftCharIndex(xw.dpy, frc[frclen].fon…
543 -
544 - f = frclen;
545 - frclen++;
546 -
547 - FcPatternDestroy(fcpattern);
548 - FcCharSetDestroy(fccharset);
549 }
550 -
551 - specs[numspecs].font = frc[f].font;
552 - specs[numspecs].glyph = glyphidx;
553 - specs[numspecs].x = (short)xp;
554 - specs[numspecs].y = (short)yp;
555 - xp += runewidth;
556 - numspecs++;
557 }
558
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 +1576,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 +1721,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 +1739,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.