From b5053179e0a64a417022a275d0a295d64312a67d Mon Sep 17 00:00:00 2001 From: William Chargin Date: Sat, 9 Jul 2022 00:46:40 -0700 Subject: [PATCH] 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 --- dsp/tty/ttyraster.c | 4 ++-- test/dsp/tty/ttyraster_test.c | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/dsp/tty/ttyraster.c b/dsp/tty/ttyraster.c index 0e2f636dd..74bde42cf 100644 --- a/dsp/tty/ttyraster.c +++ b/dsp/tty/ttyraster.c @@ -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; } diff --git a/test/dsp/tty/ttyraster_test.c b/test/dsp/tty/ttyraster_test.c index 29d61a5af..28a2aa37c 100644 --- a/test/dsp/tty/ttyraster_test.c +++ b/test/dsp/tty/ttyraster_test.c @@ -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); } ////////////////////////////////////////////////////////////////////////////////