From bfe0d2c75912697977dcd2373974896e7ba093d4 Mon Sep 17 00:00:00 2001 From: terminaldweller Date: Thu, 28 Apr 2022 11:35:25 +0430 Subject: wide glyph patch --- config.def.h | 4 +- config.h | 4 +- st.h | 94 ++++++++++++++++++++++---------------------- x.c | 124 ++++++++++++++++++++++++++++++----------------------------- 4 files changed, 112 insertions(+), 114 deletions(-) diff --git a/config.def.h b/config.def.h index c807a32..79fa5d2 100644 --- a/config.def.h +++ b/config.def.h @@ -6,10 +6,10 @@ * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html */ static char font[] = - "DejaVuSansMono Nerd Font Mono:pixelsize=14:antialias=true;autohint=true"; + "DejaVuSansMono Nerd Font Mono:pixelsize=14;antialias=true;autohint=true"; /* Spare fonts */ static char *font2[] = { - "Inconsolata for Powerline:pixelsize=12:antialias=true:autohint=true", + "DejaVuSansMono Nerd Font Mono:pixelsize=14;antialias=true;autohint=true", "Hack Nerd Font Mono:pixelsize=11:antialias=true:autohint=true", }; static int borderpx = 2; diff --git a/config.h b/config.h index c807a32..f5262bb 100644 --- a/config.h +++ b/config.h @@ -6,10 +6,10 @@ * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html */ static char font[] = - "DejaVuSansMono Nerd Font Mono:pixelsize=14:antialias=true;autohint=true"; + "DejaVuSansMono Nerd Font Mono-pixelsize=14;antialias=true;autohint=true"; /* Spare fonts */ static char *font2[] = { - "Inconsolata for Powerline:pixelsize=12:antialias=true:autohint=true", + "DejaVuSansMono Nerd Font Mono-pixelsize=14;antialias=true;autohint=true", "Hack Nerd Font Mono:pixelsize=11:antialias=true:autohint=true", }; static int borderpx = 2; diff --git a/st.h b/st.h index 519b9bd..bdc9a14 100644 --- a/st.h +++ b/st.h @@ -4,53 +4,49 @@ #include /* macros */ -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#define MAX(a, b) ((a) < (b) ? (b) : (a)) -#define LEN(a) (sizeof(a) / sizeof(a)[0]) -#define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b)) -#define DIVCEIL(n, d) (((n) + ((d) - 1)) / (d)) -#define DEFAULT(a, b) (a) = (a) ? (a) : (b) -#define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x) -#define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg != (b).fg || \ - (a).bg != (b).bg) -#define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + \ - (t1.tv_nsec-t2.tv_nsec)/1E6) -#define MODBIT(x, set, bit) ((set) ? ((x) |= (bit)) : ((x) &= ~(bit))) - -#define TRUECOLOR(r,g,b) (1 << 24 | (r) << 16 | (g) << 8 | (b)) -#define IS_TRUECOL(x) (1 << 24 & (x)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) < (b) ? (b) : (a)) +#define LEN(a) (sizeof(a) / sizeof(a)[0]) +#define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b)) +#define DIVCEIL(n, d) (((n) + ((d)-1)) / (d)) +#define DEFAULT(a, b) (a) = (a) ? (a) : (b) +#define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x) +#define ATTRCMP(a, b) \ + ((a).mode != (b).mode || (a).fg != (b).fg || (a).bg != (b).bg) +#define TIMEDIFF(t1, t2) \ + ((t1.tv_sec - t2.tv_sec) * 1000 + (t1.tv_nsec - t2.tv_nsec) / 1E6) +#define MODBIT(x, set, bit) ((set) ? ((x) |= (bit)) : ((x) &= ~(bit))) + +#define TRUECOLOR(r, g, b) (1 << 24 | (r) << 16 | (g) << 8 | (b)) +#define IS_TRUECOL(x) (1 << 24 & (x)) enum glyph_attribute { - ATTR_NULL = 0, - ATTR_BOLD = 1 << 0, - ATTR_FAINT = 1 << 1, - ATTR_ITALIC = 1 << 2, - ATTR_UNDERLINE = 1 << 3, - ATTR_BLINK = 1 << 4, - ATTR_REVERSE = 1 << 5, - ATTR_INVISIBLE = 1 << 6, - ATTR_STRUCK = 1 << 7, - ATTR_WRAP = 1 << 8, - ATTR_WIDE = 1 << 9, - ATTR_WDUMMY = 1 << 10, - ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, + ATTR_NULL = 0, + ATTR_BOLD = 1 << 0, + ATTR_FAINT = 1 << 1, + ATTR_ITALIC = 1 << 2, + ATTR_UNDERLINE = 1 << 3, + ATTR_BLINK = 1 << 4, + ATTR_REVERSE = 1 << 5, + ATTR_INVISIBLE = 1 << 6, + ATTR_STRUCK = 1 << 7, + ATTR_WRAP = 1 << 8, + ATTR_WIDE = 1 << 9, + ATTR_WDUMMY = 1 << 10, + ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, }; -enum selection_mode { - SEL_IDLE = 0, - SEL_EMPTY = 1, - SEL_READY = 2 +enum drawing_mode { + DRAW_NONE = 0, + DRAW_BG = 1 << 0, + DRAW_FG = 1 << 1, }; -enum selection_type { - SEL_REGULAR = 1, - SEL_RECTANGULAR = 2 -}; +enum selection_mode { SEL_IDLE = 0, SEL_EMPTY = 1, SEL_READY = 2 }; -enum selection_snap { - SNAP_WORD = 1, - SNAP_LINE = 2 -}; +enum selection_type { SEL_REGULAR = 1, SEL_RECTANGULAR = 2 }; + +enum selection_snap { SNAP_WORD = 1, SNAP_LINE = 2 }; typedef unsigned char uchar; typedef unsigned int uint; @@ -61,20 +57,20 @@ typedef uint_least32_t Rune; #define Glyph Glyph_ typedef struct { - Rune u; /* character code */ - ushort mode; /* attribute flags */ - uint32_t fg; /* foreground */ - uint32_t bg; /* background */ + Rune u; /* character code */ + ushort mode; /* attribute flags */ + uint32_t fg; /* foreground */ + uint32_t bg; /* background */ } Glyph; typedef Glyph *Line; typedef union { - int i; - uint ui; - float f; - const void *v; - const char *s; + int i; + uint ui; + float f; + const void *v; + const char *s; } Arg; void die(const char *, ...); diff --git a/x.c b/x.c index e394882..d96dffd 100644 --- a/x.c +++ b/x.c @@ -153,7 +153,8 @@ typedef struct { static inline ushort sixd_to_16bit(int); static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int); -static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int); +static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int, + int); static void xdrawglyph(Glyph, int, int); static void xclear(int, int, int, int); static int xgeommasktogravity(int); @@ -1336,7 +1337,7 @@ int xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, } void xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, - int x, int y) { + int x, int y, int dmode) { int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1); int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, width = charlen * win.cw; @@ -1420,44 +1421,38 @@ void xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, if (base.mode & ATTR_INVISIBLE) fg = bg; - /* Intelligent cleaning up of the borders. */ - if (x == 0) { - xclear(0, (y == 0) ? 0 : winy, borderpx, - winy + win.ch + ((winy + win.ch >= borderpx + win.th) ? win.h : 0)); - } - if (winx + width >= borderpx + win.tw) { - xclear(winx + width, (y == 0) ? 0 : winy, win.w, - ((winy + win.ch >= borderpx + win.th) ? win.h : (winy + win.ch))); - } - if (y == 0) - xclear(winx, 0, winx + width, borderpx); - if (winy + win.ch >= borderpx + win.th) - xclear(winx, winy + win.ch, winx + width, win.h); - - /* Clean up the region we want to draw to. */ - XftDrawRect(xw.draw, bg, winx, winy, width, win.ch); - - /* Set the clip region because Xft is sometimes dirty. */ - r.x = 0; - r.y = 0; - r.height = win.ch; - r.width = width; - XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1); - - /* Render the glyphs. */ - XftDrawGlyphFontSpec(xw.draw, fg, specs, len); - - /* Render underline and strikethrough. */ - if (base.mode & ATTR_UNDERLINE) { - XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1, width, 1); + if (dmode & DRAW_BG) { + /* Intelligent cleaning up of the borders. */ + if (x == 0) { + xclear(0, (y == 0) ? 0 : winy, borderpx, + winy + win.ch + + ((winy + win.ch >= borderpx + win.th) ? win.h : 0)); + } + if (winx + width >= borderpx + win.tw) { + xclear(winx + width, (y == 0) ? 0 : winy, win.w, + ((winy + win.ch >= borderpx + win.th) ? win.h : (winy + win.ch))); + } + if (y == 0) + xclear(winx, 0, winx + width, borderpx); + if (winy + win.ch >= borderpx + win.th) + xclear(winx, winy + win.ch, winx + width, win.h); + /* Fill the background */ + XftDrawRect(xw.draw, bg, winx, winy, width, win.ch); } - if (base.mode & ATTR_STRUCK) { - XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 3, width, 1); - } + if (dmode & DRAW_FG) { + /* Render the glyphs. */ + XftDrawGlyphFontSpec(xw.draw, fg, specs, len); + + /* Render underline and strikethrough. */ + if (base.mode & ATTR_UNDERLINE) { + XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1, width, 1); + } - /* Reset clip to none. */ - XftDrawSetClip(xw.draw, 0); + if (base.mode & ATTR_STRUCK) { + XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 3, width, 1); + } + } } void xdrawglyph(Glyph g, int x, int y) { @@ -1465,7 +1460,7 @@ void xdrawglyph(Glyph g, int x, int y) { XftGlyphFontSpec spec; numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y); - xdrawglyphfontspecs(&spec, g, numspecs, x, y); + xdrawglyphfontspecs(&spec, g, numspecs, x, y, DRAW_BG | DRAW_FG); } void xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) { @@ -1608,32 +1603,39 @@ int xstartdraw(void) { } void xdrawline(Line line, int x1, int y1, int x2) { - int i, x, ox, numspecs; + int i, x, ox, numspecs, numspecs_cached; Glyph base, new; - XftGlyphFontSpec *specs = xw.specbuf; - - numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1); - i = ox = 0; - for (x = x1; x < x2 && i < numspecs; x++) { - new = line[x]; - if (new.mode == ATTR_WDUMMY) - continue; - if (selected(x, y1)) - new.mode ^= ATTR_REVERSE; - if (i > 0 && ATTRCMP(base, new)) { - xdrawglyphfontspecs(specs, base, i, ox, y1); - specs += i; - numspecs -= i; - i = 0; - } - if (i == 0) { - ox = x; - base = new; + XftGlyphFontSpec *specs; + + numspecs_cached = xmakeglyphfontspecs(xw.specbuf, &line[x1], x2 - x1, x1, y1); + + /* Draw line in 2 passes: background and foreground. This way wide glyphs + won't get truncated (#223) */ + for (int dmode = DRAW_BG; dmode <= DRAW_FG; dmode <<= 1) { + specs = xw.specbuf; + numspecs = numspecs_cached; + i = ox = 0; + for (x = x1; x < x2 && i < numspecs; x++) { + new = line[x]; + if (new.mode == ATTR_WDUMMY) + continue; + if (selected(x, y1)) + new.mode ^= ATTR_REVERSE; + if (i > 0 && ATTRCMP(base, new)) { + xdrawglyphfontspecs(specs, base, i, ox, y1, dmode); + specs += i; + numspecs -= i; + i = 0; + } + if (i == 0) { + ox = x; + base = new; + } + i++; } - i++; + if (i > 0) + xdrawglyphfontspecs(specs, base, i, ox, y1, dmode); } - if (i > 0) - xdrawglyphfontspecs(specs, base, i, ox, y1); } void xfinishdraw(void) { -- cgit v1.2.3