Added wide glyphs patch.

This commit is contained in:
CronyAkatsuki 2023-03-04 12:45:08 +01:00
parent 7888ab5ae6
commit cd0e6f6e3a
6 changed files with 286 additions and 4963 deletions

View File

@ -0,0 +1,213 @@
From 9583955da47177c9557210f70baaaf9511ba106c Mon Sep 17 00:00:00 2001
From: wael <40663@protonmail.com>
Date: Mon, 11 Apr 2022 17:14:06 +0300
Subject: [PATCH] boxdraw support for glyph wide support
---
st.h | 6 +++
x.c | 139 ++++++++++++++++++++++++++++++-----------------------------
2 files changed, 76 insertions(+), 69 deletions(-)
diff --git a/st.h b/st.h
index 07a7c66..3b8c97d 100644
--- a/st.h
+++ b/st.h
@@ -37,6 +37,12 @@ enum glyph_attribute {
ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
};
+enum drawing_mode {
+ DRAW_NONE = 0,
+ DRAW_BG = 1 << 0,
+ DRAW_FG = 1 << 1,
+};
+
enum selection_mode {
SEL_IDLE = 0,
SEL_EMPTY = 1,
diff --git a/x.c b/x.c
index bf6bbf9..1311c0d 100644
--- a/x.c
+++ b/x.c
@@ -142,7 +142,7 @@ 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);
@@ -1379,7 +1379,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
}
void
-xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y)
+xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, 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,
@@ -1470,51 +1470,45 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
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);
-
- if (base.mode & ATTR_BOXDRAW) {
- drawboxes(winx, winy, width / len, win.ch, fg, bg, specs, len);
- } else {
- /* Render the glyphs. */
- XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
- }
+ 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 (dmode & DRAW_FG) {
+ if (base.mode & ATTR_BOXDRAW) {
+ drawboxes(winx, winy, width / len, win.ch, fg, bg, specs, len);
+ } else {
+ /* 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 * chscale + 1,
- width, 1);
- }
+ /* Render underline and strikethrough. */
+ if (base.mode & ATTR_UNDERLINE) {
+ XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1,
+ width, 1);
+ }
- if (base.mode & ATTR_STRUCK) {
- XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent * chscale / 3,
- 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
@@ -1524,7 +1518,7 @@ 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
@@ -1659,32 +1653,39 @@ 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
--
2.35.1

2668
st.c.orig

File diff suppressed because it is too large Load Diff

6
st.h
View File

@ -37,6 +37,12 @@ enum glyph_attribute {
ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
}; };
enum drawing_mode {
DRAW_NONE = 0,
DRAW_BG = 1 << 0,
DRAW_FG = 1 << 1,
};
enum selection_mode { enum selection_mode {
SEL_IDLE = 0, SEL_IDLE = 0,
SEL_EMPTY = 1, SEL_EMPTY = 1,

126
st.h.orig
View File

@ -1,126 +0,0 @@
/* See LICENSE for license details. */
#include <stdint.h>
#include <sys/types.h>
/* 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))
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,
};
enum selection_mode {
SEL_IDLE = 0,
SEL_EMPTY = 1,
SEL_READY = 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;
typedef unsigned long ulong;
typedef unsigned short ushort;
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 */
} Glyph;
typedef Glyph *Line;
typedef union {
int i;
uint ui;
float f;
const void *v;
const char *s;
} Arg;
void die(const char *, ...);
void redraw(void);
void draw(void);
void printscreen(const Arg *);
void printsel(const Arg *);
void sendbreak(const Arg *);
void toggleprinter(const Arg *);
int tattrset(int);
void tnew(int, int);
void tresize(int, int);
void tsetdirtattr(int);
void ttyhangup(void);
int ttynew(const char *, char *, const char *, char **);
size_t ttyread(void);
void ttyresize(int, int);
void ttywrite(const char *, size_t, int);
void resettitle(void);
void selclear(void);
void selinit(void);
void selstart(int, int, int);
void selextend(int, int, int, int);
int selected(int, int);
char *getsel(void);
size_t utf8encode(Rune, char *);
void *xmalloc(size_t);
void *xrealloc(void *, size_t);
char *xstrdup(const char *);
/* config.h globals */
extern char *utmp;
extern char *scroll;
extern char *stty_args;
extern char *vtiden;
extern wchar_t *worddelimiters;
extern int allowaltscreen;
extern int allowwindowops;
extern char *termname;
extern unsigned int tabspaces;
extern unsigned int defaultfg;
extern unsigned int defaultbg;
extern unsigned int defaultcs;

133
x.c
View File

@ -143,7 +143,7 @@ typedef struct {
static inline ushort sixd_to_16bit(int); static inline ushort sixd_to_16bit(int);
static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, 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 xdrawglyph(Glyph, int, int);
static void xclear(int, int, int, int); static void xclear(int, int, int, int);
static int xgeommasktogravity(int); static int xgeommasktogravity(int);
@ -1383,7 +1383,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
} }
void void
xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y) xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y, int dmode)
{ {
int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1); int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1);
int winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch, int winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch,
@ -1474,51 +1474,45 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
if (base.mode & ATTR_INVISIBLE) if (base.mode & ATTR_INVISIBLE)
fg = bg; fg = bg;
/* Intelligent cleaning up of the borders. */ if (dmode & DRAW_BG) {
if (x == 0) { /* Intelligent cleaning up of the borders. */
xclear(0, (y == 0)? 0 : winy, win.hborderpx, if (x == 0) {
winy + win.ch + xclear(0, (y == 0)? 0 : winy, borderpx,
((winy + win.ch >= win.vborderpx + win.th)? win.h : 0)); winy + win.ch +
} ((winy + win.ch >= borderpx + win.th)? win.h : 0));
if (winx + width >= win.hborderpx + win.tw) { }
xclear(winx + width, (y == 0)? 0 : winy, win.w, if (winx + width >= borderpx + win.tw) {
((winy + win.ch >= win.vborderpx + win.th)? win.h : (winy + win.ch))); 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, win.vborderpx); if (y == 0)
if (winy + win.ch >= win.vborderpx + win.th) xclear(winx, 0, winx + width, borderpx);
xclear(winx, winy + win.ch, winx + width, win.h); 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);
}
/* 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. */ if (dmode & DRAW_FG) {
r.x = 0; if (base.mode & ATTR_BOXDRAW) {
r.y = 0; drawboxes(winx, winy, width / len, win.ch, fg, bg, specs, len);
r.height = win.ch; } else {
r.width = width; /* Render the glyphs. */
XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1); XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
}
if (base.mode & ATTR_BOXDRAW) { /* Render underline and strikethrough. */
drawboxes(winx, winy, width / len, win.ch, fg, bg, specs, len); if (base.mode & ATTR_UNDERLINE) {
} else { XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1,
/* Render the glyphs. */ width, 1);
XftDrawGlyphFontSpec(xw.draw, fg, specs, len); }
}
/* Render underline and strikethrough. */ if (base.mode & ATTR_STRUCK) {
if (base.mode & ATTR_UNDERLINE) { XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 3,
XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent * chscale + 1, width, 1);
width, 1); }
} }
if (base.mode & ATTR_STRUCK) {
XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent * chscale / 3,
width, 1);
}
/* Reset clip to none. */
XftDrawSetClip(xw.draw, 0);
} }
void void
@ -1528,7 +1522,7 @@ xdrawglyph(Glyph g, int x, int y)
XftGlyphFontSpec spec; XftGlyphFontSpec spec;
numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y); numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y);
xdrawglyphfontspecs(&spec, g, numspecs, x, y); xdrawglyphfontspecs(&spec, g, numspecs, x, y, DRAW_BG | DRAW_FG);
} }
void void
@ -1663,32 +1657,39 @@ xstartdraw(void)
void void
xdrawline(Line line, int x1, int y1, int x2) xdrawline(Line line, int x1, int y1, int x2)
{ {
int i, x, ox, numspecs; int i, x, ox, numspecs, numspecs_cached;
Glyph base, new; Glyph base, new;
XftGlyphFontSpec *specs = xw.specbuf; XftGlyphFontSpec *specs;
numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1); numspecs_cached = xmakeglyphfontspecs(xw.specbuf, &line[x1], x2 - x1, x1, y1);
i = ox = 0;
for (x = x1; x < x2 && i < numspecs; x++) { /* Draw line in 2 passes: background and foreground. This way wide glyphs
new = line[x]; won't get truncated (#223) */
if (new.mode == ATTR_WDUMMY) for (int dmode = DRAW_BG; dmode <= DRAW_FG; dmode <<= 1) {
continue; specs = xw.specbuf;
if (selected(x, y1)) numspecs = numspecs_cached;
new.mode ^= ATTR_REVERSE; i = ox = 0;
if (i > 0 && ATTRCMP(base, new)) { for (x = x1; x < x2 && i < numspecs; x++) {
xdrawglyphfontspecs(specs, base, i, ox, y1); new = line[x];
specs += i; if (new.mode == ATTR_WDUMMY)
numspecs -= i; continue;
i = 0; 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++;
} }
if (i == 0) { if (i > 0)
ox = x; xdrawglyphfontspecs(specs, base, i, ox, y1, dmode);
base = new;
}
i++;
} }
if (i > 0)
xdrawglyphfontspecs(specs, base, i, ox, y1);
} }
void void

2103
x.c.orig

File diff suppressed because it is too large Load Diff