ttyraster: reset ANSI attributes after each line

This fixes a bug that appears when using `printimage` in my `xterm` or
`gnome-terminal`. When printing a line causes the viewport to scroll,
the last color painted would extend to the last column of the window
rather than the last column of the image. (This is especially noticeable
when rendering a narrow image in a wide window.) A similar artifact
would occur with the last line, which would appear in the color of the
bottom-right corner of the image.

By slapping an `\e[0m` before each newline and before the end of the
image, we avoid these artifacts.

![Screenshots of the output of `printimage` before and after this
change. Each screenshot shows `lemurs.png` printed twice; the first copy
is only partially visible because the window has scrolled. In the
"before" picture, the second copy has extra bands of color off to the
right of the image starting about halfway down, plus a gray band beneath
the image. The "after" picture has no such artifacts.][ss]

[ss]: https://user-images.githubusercontent.com/4317806/178096633-9a9e46a7-360b-49c1-8569-e6b401b81d09.png

wchargin-branch: ttyraster-reset-each-line
wchargin-source: dfd8233b06783f16cf5fd40285f7d1bc022c9cb2
This commit is contained in:
William Chargin 2022-07-09 00:46:40 -07:00
parent c5b9902ac9
commit b5053179e0
2 changed files with 9 additions and 9 deletions

View file

@ -775,7 +775,7 @@ char *ttyraster(char *v, const struct TtyRgb *c, size_t yn, size_t xn,
struct Glyph glyph;
struct TtyRgb chun[4], lastchunk[4];
for (y = 0; y < yn; y += 2, c += xn) {
if (y) *v++ = '\r', *v++ = '\n';
if (y) v = stpcpy(v, "\e[0m\r\n");
for (x = 0; x < xn; x += 2, c += 2) {
CopyChunk(chun, c, xn);
if (ttyquant()->alg == kTtyQuantTrue) {
@ -795,6 +795,6 @@ char *ttyraster(char *v, const struct TtyRgb *c, size_t yn, size_t xn,
memcpy(lastchunk, chun, sizeof(chun));
}
}
*v = '\0';
v = stpcpy(v, "\e[0m");
return v;
}

View file

@ -43,7 +43,7 @@ void ttyraster2x2_true(void) {
TEST(ttyraster, testCorner) {
ttyraster_true_setup();
ttyraster2x2_true();
EXPECT_STREQ("\e[48;2;139;0;0;38;2;3;3;3m▝", vtbuf);
EXPECT_STREQ("\e[48;2;139;0;0;38;2;3;3;3m▝\e[0m", vtbuf);
}
TEST(ttyraster, testFullBlock_favorsSpace) {
@ -54,7 +54,7 @@ TEST(ttyraster, testFullBlock_favorsSpace) {
{DARKRED, DARKRED},
},
2, 2, kBlack, kBlack);
EXPECT_STREQ("\e[48;2;139;0;0m ", vtbuf);
EXPECT_STREQ("\e[48;2;139;0;0m \e[0m", vtbuf);
}
TEST(ttyraster, testFullBlock_favorsUnicodeWhenCurrenttFgMatchesButNotBg) {
@ -65,7 +65,7 @@ TEST(ttyraster, testFullBlock_favorsUnicodeWhenCurrenttFgMatchesButNotBg) {
{DARKRED, DARKRED, GRAY1, GRAY1},
},
2, 4, kBlack, kBlack);
EXPECT_STREQ("\e[48;2;139;0;0;38;2;3;3;3m▝█", vtbuf);
EXPECT_STREQ("\e[48;2;139;0;0;38;2;3;3;3m▝█\e[0m", vtbuf);
}
TEST(ttyraster, testFullBlock_forcesSwitchBackToSpaceForRuns) {
@ -76,7 +76,7 @@ TEST(ttyraster, testFullBlock_forcesSwitchBackToSpaceForRuns) {
{DARKRED, DARKRED, GRAY1, GRAY1, GRAY1, GRAY1, GRAY1, GRAY1},
},
2, 8, kBlack, kBlack);
EXPECT_STREQ("\e[48;2;139;0;0;38;2;3;3;3m▝█\e[48;2;3;3;3m ", vtbuf);
EXPECT_STREQ("\e[48;2;139;0;0;38;2;3;3;3m▝█\e[48;2;3;3;3m \e[0m", vtbuf);
}
////////////////////////////////////////////////////////////////////////////////
@ -89,7 +89,7 @@ TEST(ttyraster_cp437, testSide) {
{DARKRED, GRAY1},
},
2, 2, kBlack, kBlack);
EXPECT_STREQ("\e[48;2;3;3;3;38;2;139;0;0m▌", vtbuf);
EXPECT_STREQ("\e[48;2;3;3;3;38;2;139;0;0m▌\e[0m", vtbuf);
}
////////////////////////////////////////////////////////////////////////////////
@ -110,7 +110,7 @@ void ttyraster2x2_xterm256(void) {
TEST(ttyraster_xterm256, testCorner) {
ttyraster_xterm256_setup();
ttyraster2x2_xterm256();
EXPECT_STREQ("\e[48;5;16;38;5;231m▝", vtbuf);
EXPECT_STREQ("\e[48;5;16;38;5;231m▝\e[0m", vtbuf);
}
void ttyraster6x2_xterm256(void) {
@ -125,7 +125,7 @@ void ttyraster6x2_xterm256(void) {
TEST(ttyraster_xterm256, testCornerRepeat3) {
ttyraster_xterm256_setup();
ttyraster6x2_xterm256();
EXPECT_STREQ("\e[48;5;16;38;5;231m▝▝▝", vtbuf);
EXPECT_STREQ("\e[48;5;16;38;5;231m▝▝▝\e[0m", vtbuf);
}
////////////////////////////////////////////////////////////////////////////////