Skip to content

Commit e3b821d

Browse files
committed
Fix wide glyphs truncation
1 parent ca42c0c commit e3b821d

File tree

2 files changed

+73
-56
lines changed

2 files changed

+73
-56
lines changed

st.h

+6
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ enum glyph_attribute {
3737
ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
3838
};
3939

40+
enum drawing_mode {
41+
DRAW_NONE = 0,
42+
DRAW_BG = 1 << 0,
43+
DRAW_FG = 1 << 1,
44+
};
45+
4046
enum selection_mode {
4147
SEL_IDLE = 0,
4248
SEL_EMPTY = 1,

x.c

+67-56
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ typedef struct {
152152

153153
static inline ushort sixd_to_16bit(int);
154154
static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int);
155-
static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int);
155+
static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int, int);
156156
static void xdrawglyph(Glyph, int, int);
157157
static void xclear(int, int, int, int);
158158
static int xgeommasktogravity(int);
@@ -1445,7 +1445,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
14451445
}
14461446

14471447
void
1448-
xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y)
1448+
xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y, int dmode)
14491449
{
14501450
int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1);
14511451
int winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch,
@@ -1531,40 +1531,44 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
15311531
if (base.mode & ATTR_INVISIBLE)
15321532
fg = bg;
15331533

1534-
/* Intelligent cleaning up of the borders. */
1535-
if (x == 0) {
1536-
xclear(0, (y == 0)? 0 : winy, win.vborderpx,
1537-
winy + win.ch +
1538-
((winy + win.ch >= win.vborderpx + win.th)? win.h : 0));
1539-
}
1540-
if (winx + width >= win.hborderpx + win.tw) {
1541-
xclear(winx + width, (y == 0)? 0 : winy, win.w,
1542-
((winy + win.ch >= win.vborderpx + win.th)? win.h : (winy + win.ch)));
1543-
}
1544-
if (y == 0)
1545-
xclear(winx, 0, winx + width, win.hborderpx);
1546-
if (winy + win.ch >= win.vborderpx + win.th)
1547-
xclear(winx, winy + win.ch, winx + width, win.h);
1548-
1549-
/* Clean up the region we want to draw to. */
1550-
XftDrawRect(xw.draw, bg, winx, winy, width, win.ch);
1534+
if (dmode & DRAW_BG) {
1535+
/* Intelligent cleaning up of the borders. */
1536+
if (x == 0) {
1537+
xclear(0, (y == 0)? 0 : winy, win.vborderpx,
1538+
winy + win.ch +
1539+
((winy + win.ch >= win.vborderpx + win.th)? win.h : 0));
1540+
}
1541+
if (winx + width >= win.hborderpx + win.tw) {
1542+
xclear(winx + width, (y == 0)? 0 : winy, win.w,
1543+
((winy + win.ch >= win.vborderpx + win.th)? win.h : (winy + win.ch)));
1544+
}
1545+
if (y == 0)
1546+
xclear(winx, 0, winx + width, win.hborderpx);
1547+
if (winy + win.ch >= win.vborderpx + win.th)
1548+
xclear(winx, winy + win.ch, winx + width, win.h);
15511549

1552-
if (base.mode & ATTR_BOXDRAW) {
1553-
drawboxes(winx, winy, width / len, win.ch, fg, bg, specs, len);
1554-
} else {
1555-
/* Render the glyphs. */
1556-
XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
1550+
/* Fill the background */
1551+
XftDrawRect(xw.draw, bg, winx, winy, width, win.ch);
15571552
}
15581553

1559-
/* Render underline and strikethrough. */
1560-
if (base.mode & ATTR_UNDERLINE) {
1561-
XftDrawRect(xw.draw, fg, winx, winy + win.cyo + dc.font.ascent + 1,
1562-
width, 1);
1563-
}
1554+
if (dmode & DRAW_FG) {
1555+
if (base.mode & ATTR_BOXDRAW) {
1556+
drawboxes(winx, winy, width / len, win.ch, fg, bg, specs, len);
1557+
} else {
1558+
/* Render the glyphs. */
1559+
XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
1560+
}
15641561

1565-
if (base.mode & ATTR_STRUCK) {
1566-
XftDrawRect(xw.draw, fg, winx, winy + win.cyo + 2 * dc.font.ascent / 3,
1567-
width, 1);
1562+
/* Render underline and strikethrough. */
1563+
if (base.mode & ATTR_UNDERLINE) {
1564+
XftDrawRect(xw.draw, fg, winx, winy + win.cyo + dc.font.ascent + 1,
1565+
width, 1);
1566+
}
1567+
1568+
if (base.mode & ATTR_STRUCK) {
1569+
XftDrawRect(xw.draw, fg, winx, winy + win.cyo + 2 * dc.font.ascent / 3,
1570+
width, 1);
1571+
}
15681572
}
15691573
}
15701574

@@ -1575,7 +1579,7 @@ xdrawglyph(Glyph g, int x, int y)
15751579
XftGlyphFontSpec spec;
15761580

15771581
numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y);
1578-
xdrawglyphfontspecs(&spec, g, numspecs, x, y);
1582+
xdrawglyphfontspecs(&spec, g, numspecs, x, y, DRAW_BG | DRAW_FG);
15791583
}
15801584

15811585
void
@@ -1694,32 +1698,39 @@ xstartdraw(void)
16941698
void
16951699
xdrawline(Line line, int x1, int y1, int x2)
16961700
{
1697-
int i, x, ox, numspecs;
1701+
int i, x, ox, numspecs, numspecs_cached;
16981702
Glyph base, new;
1699-
XftGlyphFontSpec *specs = xw.specbuf;
1700-
1701-
numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1);
1702-
i = ox = 0;
1703-
for (x = x1; x < x2 && i < numspecs; x++) {
1704-
new = line[x];
1705-
if (new.mode == ATTR_WDUMMY)
1706-
continue;
1707-
if (selected(x, y1))
1708-
new.mode ^= ATTR_REVERSE;
1709-
if (i > 0 && ATTRCMP(base, new)) {
1710-
xdrawglyphfontspecs(specs, base, i, ox, y1);
1711-
specs += i;
1712-
numspecs -= i;
1713-
i = 0;
1714-
}
1715-
if (i == 0) {
1716-
ox = x;
1717-
base = new;
1703+
XftGlyphFontSpec *specs;
1704+
1705+
numspecs_cached = xmakeglyphfontspecs(xw.specbuf, &line[x1], x2 - x1, x1, y1);
1706+
1707+
/* Draw line in 2 passes: background and foreground. This way wide glyphs
1708+
won't get truncated (#223) */
1709+
for (int dmode = DRAW_BG; dmode <= DRAW_FG; dmode <<= 1) {
1710+
specs = xw.specbuf;
1711+
numspecs = numspecs_cached;
1712+
i = ox = 0;
1713+
for (x = x1; x < x2 && i < numspecs; x++) {
1714+
new = line[x];
1715+
if (new.mode == ATTR_WDUMMY)
1716+
continue;
1717+
if (selected(x, y1))
1718+
new.mode ^= ATTR_REVERSE;
1719+
if (i > 0 && ATTRCMP(base, new)) {
1720+
xdrawglyphfontspecs(specs, base, i, ox, y1, dmode);
1721+
specs += i;
1722+
numspecs -= i;
1723+
i = 0;
1724+
}
1725+
if (i == 0) {
1726+
ox = x;
1727+
base = new;
1728+
}
1729+
i++;
17181730
}
1719-
i++;
1731+
if (i > 0)
1732+
xdrawglyphfontspecs(specs, base, i, ox, y1, dmode);
17201733
}
1721-
if (i > 0)
1722-
xdrawglyphfontspecs(specs, base, i, ox, y1);
17231734
}
17241735

17251736
void

0 commit comments

Comments
 (0)