mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
sixel: respect sixel aspect ratio
That is, parse P1 when initializing a new sixel, and don’t ignore pad/pad in the raster attributes command. The default aspect ratio is 2:1, but most sixels will override it in the raster attributes command (to 1:1).
This commit is contained in:
parent
66d9b8da60
commit
d6d143e2a6
3 changed files with 52 additions and 14 deletions
|
|
@ -49,6 +49,7 @@
|
|||
* Meson option `utmp-backend=none|libutempter|ulog|auto`. The default
|
||||
is `auto`, which will select `libutempter` on Linux, `ulog` on
|
||||
FreeBSD, and `none` for all others.
|
||||
* Sixel aspect ratio.
|
||||
|
||||
|
||||
### Changed
|
||||
|
|
@ -74,6 +75,8 @@
|
|||
sixel is visible. For example, `cat`:ing a sixel in the shell will
|
||||
typically result in the last row not being visible, unless a newline
|
||||
is explicitly added.
|
||||
* Default sixel aspect ratio is now 2:1 instead of 1:1.
|
||||
|
||||
|
||||
[1371]: https://codeberg.org/dnkl/foot/pulls/1371
|
||||
[1360]: https://codeberg.org/dnkl/foot/issues/1360
|
||||
|
|
|
|||
54
sixel.c
54
sixel.c
|
|
@ -38,18 +38,33 @@ sixel_init(struct terminal *term, int p1, int p2, int p3)
|
|||
xassert(term->sixel.image.data == NULL);
|
||||
xassert(term->sixel.palette_size <= SIXEL_MAX_COLORS);
|
||||
|
||||
/* Default aspect ratio is 2:1 */
|
||||
const int pad = 1;
|
||||
const int pan =
|
||||
(p1 == 2) ? 5 :
|
||||
(p1 == 3 || p1 == 4) ? 3 :
|
||||
(p1 == 7 || p1 == 8 || p1 == 9) ? 1 : 2;
|
||||
|
||||
LOG_DBG("initializing sixel with "
|
||||
"p1=%d (pan=%d, pad=%d, AR=%d:%d), "
|
||||
"p2=%d (transparent=%d), "
|
||||
"p3=%d (ignored)",
|
||||
p1, pan, pad, pan, pad, p2, p2 == 1, p3);
|
||||
|
||||
term->sixel.state = SIXEL_DECSIXEL;
|
||||
term->sixel.pos = (struct coord){0, 0};
|
||||
term->sixel.max_non_empty_row_no = -1;
|
||||
term->sixel.row_byte_ofs = 0;
|
||||
term->sixel.color_idx = 0;
|
||||
term->sixel.pan = pan;
|
||||
term->sixel.pad = pad;
|
||||
term->sixel.param = 0;
|
||||
term->sixel.param_idx = 0;
|
||||
memset(term->sixel.params, 0, sizeof(term->sixel.params));
|
||||
term->sixel.transparent_bg = p2 == 1;
|
||||
term->sixel.image.data = xmalloc(1 * 6 * sizeof(term->sixel.image.data[0]));
|
||||
term->sixel.image.width = 1;
|
||||
term->sixel.image.height = 6;
|
||||
term->sixel.image.data = NULL;
|
||||
term->sixel.image.width = 0;
|
||||
term->sixel.image.height = 6 * pan;
|
||||
|
||||
/* TODO: default palette */
|
||||
|
||||
|
|
@ -104,9 +119,6 @@ sixel_init(struct terminal *term, int p1, int p2, int p3)
|
|||
? 0x00000000u
|
||||
: bg;
|
||||
|
||||
for (size_t i = 0; i < 1 * 6; i++)
|
||||
term->sixel.image.data[i] = term->sixel.default_bg;
|
||||
|
||||
count = 0;
|
||||
}
|
||||
|
||||
|
|
@ -1045,7 +1057,7 @@ sixel_unhook(struct terminal *term)
|
|||
|
||||
if (do_scroll) {
|
||||
/* Yes, truncate last row. This matches XTerm’s, and VT382’s behavior */
|
||||
const int linefeed_count = image.height / term->cell_height;
|
||||
const int linefeed_count = (image.height - 6 * term->sixel.pan + 1) / term->cell_height;
|
||||
for (size_t i = 0; i < linefeed_count; i++)
|
||||
term_linefeed(term);
|
||||
|
||||
|
|
@ -1131,7 +1143,8 @@ resize_horizontally(struct terminal *term, int new_width)
|
|||
const int old_width = term->sixel.image.width;
|
||||
const int height = term->sixel.image.height;
|
||||
|
||||
int alloc_height = (height + 6 - 1) / 6 * 6;
|
||||
const int sixel_row_height = 6 * term->sixel.pan;
|
||||
int alloc_height = (height + sixel_row_height - 1) / sixel_row_height * sixel_row_height;
|
||||
|
||||
xassert(new_width > 0);
|
||||
xassert(alloc_height > 0);
|
||||
|
|
@ -1176,9 +1189,14 @@ resize_vertically(struct terminal *term, int new_height)
|
|||
|
||||
int alloc_height = (new_height + 6 - 1) / 6 * 6;
|
||||
|
||||
xassert(width > 0);
|
||||
xassert(new_height > 0);
|
||||
|
||||
if (unlikely(width == 0)) {
|
||||
xassert(term->sixel.image.data == NULL);
|
||||
term->sixel.image.height = new_height;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t *new_data = realloc(
|
||||
old_data, width * alloc_height * sizeof(uint32_t));
|
||||
|
||||
|
|
@ -1283,7 +1301,7 @@ sixel_add(struct terminal *term, int col, int width, uint32_t color, uint8_t six
|
|||
int max_non_empty_row = -1;
|
||||
int row = term->sixel.pos.row;
|
||||
|
||||
for (int i = 0; i < 6; i++, sixel >>= 1, data += width) {
|
||||
for (int i = 0; i < 6 * term->sixel.pan; i++, sixel >>= 1, data += width) {
|
||||
if (sixel & 1) {
|
||||
*data = color;
|
||||
max_non_empty_row = row + i;
|
||||
|
|
@ -1303,6 +1321,8 @@ sixel_add_many(struct terminal *term, uint8_t c, unsigned count)
|
|||
int col = term->sixel.pos.col;
|
||||
int width = term->sixel.image.width;
|
||||
|
||||
count *= term->sixel.pad;
|
||||
|
||||
if (unlikely(col + count - 1 >= width)) {
|
||||
resize_horizontally(term, col + count);
|
||||
width = term->sixel.image.width;
|
||||
|
|
@ -1352,13 +1372,13 @@ decsixel(struct terminal *term, uint8_t c)
|
|||
break;
|
||||
|
||||
case '-':
|
||||
term->sixel.pos.row += 6;
|
||||
term->sixel.pos.row += 6 * term->sixel.pan;
|
||||
term->sixel.pos.col = 0;
|
||||
term->sixel.row_byte_ofs += term->sixel.image.width * 6;
|
||||
term->sixel.row_byte_ofs += term->sixel.image.width * 6 * term->sixel.pan;
|
||||
|
||||
if (term->sixel.pos.row >= term->sixel.image.height) {
|
||||
if (!resize_vertically(term, term->sixel.pos.row + 6))
|
||||
term->sixel.pos.col = term->sixel.max_width + 1;
|
||||
if (!resize_vertically(term, term->sixel.pos.row + 6 * term->sixel.pan))
|
||||
term->sixel.pos.col = term->sixel.max_width + 1 * term->sixel.pad;
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -1415,6 +1435,12 @@ decgra(struct terminal *term, uint8_t c)
|
|||
pan = pan > 0 ? pan : 1;
|
||||
pad = pad > 0 ? pad : 1;
|
||||
|
||||
pv *= pan;
|
||||
ph *= pad;
|
||||
|
||||
term->sixel.pan = pan;
|
||||
term->sixel.pad = pad;
|
||||
|
||||
LOG_DBG("pan=%u, pad=%u (aspect ratio = %u), size=%ux%u",
|
||||
pan, pad, pan / pad, ph, pv);
|
||||
|
||||
|
|
|
|||
|
|
@ -634,6 +634,15 @@ struct terminal {
|
|||
int height; /* Image height, in pixels */
|
||||
} image;
|
||||
|
||||
/*
|
||||
* Pan is the vertical shape of a pixel
|
||||
* Pad is the horizontal shape of a pixel
|
||||
*
|
||||
* pan/pad is the sixel’s aspect ratio
|
||||
*/
|
||||
int pan;
|
||||
int pad;
|
||||
|
||||
bool scrolling:1; /* Private mode 80 */
|
||||
bool use_private_palette:1; /* Private mode 1070 */
|
||||
bool cursor_right_of_graphics:1; /* Private mode 8452 */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue