From 4aa980a6a2ce3c3dde0df99438b88969deed3e36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 16 Feb 2021 19:37:49 +0100 Subject: [PATCH 1/3] sixel: implement private mode 1070 - private color palette When enabled (the default), sixels use private color registers. That is, the color palette from the last sixel is *not* re-used. When disabled, sixels share (i.e. re-use) the same color palette. Closes #362 --- CHANGELOG.md | 2 ++ csi.c | 7 +++++++ sixel.c | 32 ++++++++++++++++++++++++++------ terminal.c | 1 + terminal.h | 8 +++++++- 5 files changed, 43 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 86bc376a..e4a00be3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,8 @@ `footclient` (https://codeberg.org/dnkl/foot/issues/337). * `-D,--working-directory=DIR` to both `foot` and `footclient` (https://codeberg.org/dnkl/foot/issues/347) +* `DECSET 1070` - sixel private color palette + (https://codeberg.org/dnkl/foot/issues/362). ### Changed diff --git a/csi.c b/csi.c index 7a50ef5b..d7a26e3c 100644 --- a/csi.c +++ b/csi.c @@ -544,6 +544,10 @@ decset_decrst(struct terminal *term, unsigned param, bool enable) } break; + case 1070: + term->sixel.use_private_palette = enable; + break; + case 2004: term->bracketed_paste = enable; break; @@ -607,6 +611,7 @@ decrqm(const struct terminal *term, unsigned param, bool *enabled) case 47: /* FALLTHROUGH */ case 1047: /* FALLTHROUGH */ case 1049: *enabled = term->grid == &term->alt; return true; + case 1079: *enabled = term->sixel.use_private_palette; return true; case 2004: *enabled = term->bracketed_paste; return true; case 27127: *enabled = term->modify_escape_key; return true; case 737769: *enabled = term_ime_is_enabled(term); return true; @@ -646,6 +651,7 @@ xtsave(struct terminal *term, unsigned param) case 1047: term->xtsave.alt_screen = term->grid == &term->alt; break; case 1048: term_save_cursor(term); break; case 1049: term->xtsave.alt_screen = term->grid == &term->alt; break; + case 1070: term->xtsave.sixel_private_palette = term->sixel.use_private_palette; break; case 2004: term->xtsave.bracketed_paste = term->bracketed_paste; break; case 27127: term->xtsave.modify_escape_key = term->modify_escape_key; break; case 737769: term->xtsave.ime = term_ime_is_enabled(term); break; @@ -684,6 +690,7 @@ xtrestore(struct terminal *term, unsigned param) case 1047: enable = term->xtsave.alt_screen; break; case 1048: enable = true; break; case 1049: enable = term->xtsave.alt_screen; break; + case 1070: enable = term->xtsave.sixel_private_palette; break; case 2004: enable = term->xtsave.bracketed_paste; break; case 27127: enable = term->xtsave.modify_escape_key; break; case 737769: enable = term->xtsave.ime; break; diff --git a/sixel.c b/sixel.c index 4a71f9ee..dede6e10 100644 --- a/sixel.c +++ b/sixel.c @@ -18,7 +18,8 @@ static size_t count; void sixel_fini(struct terminal *term) { - free(term->sixel.palette); + free(term->sixel.private_palette); + free(term->sixel.shared_palette); } static uint32_t @@ -46,17 +47,36 @@ sixel_init(struct terminal *term) term->sixel.image.height = 6; term->sixel.image.autosize = true; - if (term->sixel.palette == NULL) { - term->sixel.palette = xcalloc( - term->sixel.palette_size, sizeof(term->sixel.palette[0])); + /* TODO: default palette */ + + if (term->sixel.use_private_palette) { + if (term->sixel.private_palette == NULL) { + term->sixel.private_palette = xcalloc( + term->sixel.palette_size, sizeof(term->sixel.private_palette[0])); + } else { + /* Private palette - i.e. each sixel starts with a clean palette */ + memset( + term->sixel.private_palette, + 0, + term->sixel.palette_size * sizeof(term->sixel.private_palette[0])); + } + + term->sixel.palette = term->sixel.private_palette; + } else { + if (term->sixel.shared_palette == NULL) { + term->sixel.shared_palette = xcalloc( + term->sixel.palette_size, sizeof(term->sixel.shared_palette[0])); + } else { + /* Shared palette - do *not* reset palette for new sixels */ + } + + term->sixel.palette = term->sixel.shared_palette; } for (size_t i = 0; i < 1 * 6; i++) term->sixel.image.data[i] = color_with_alpha(term, term->colors.bg); count = 0; - - /* TODO: default palette */ } void diff --git a/terminal.c b/terminal.c index 3710f005..60ed8694 100644 --- a/terminal.c +++ b/terminal.c @@ -1180,6 +1180,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, .upper_fd = delay_upper_fd, }, .sixel = { + .use_private_palette = true, .palette_size = SIXEL_MAX_COLORS, .max_width = SIXEL_MAX_WIDTH, .max_height = SIXEL_MAX_HEIGHT, diff --git a/terminal.h b/terminal.h index acff9d06..632f6029 100644 --- a/terminal.h +++ b/terminal.h @@ -359,6 +359,8 @@ struct terminal { uint32_t alt_screen:1; uint32_t modify_escape_key:1; uint32_t ime:1; + + uint32_t sixel_private_palette:1; } xtsave; char *window_title; @@ -519,7 +521,9 @@ struct terminal { struct coord pos; /* Current sixel coordinate */ int color_idx; /* Current palette index */ int max_col; /* Largest column index we've seen (aka the image width) */ - uint32_t *palette; /* Color palette */ + uint32_t *private_palette; /* Private palette, used when private mode 1070 is enabled */ + uint32_t *shared_palette; /* Shared palette, used when private mode 1070 is disabled */ + uint32_t *palette; /* Points to either private_palette or shared_palette */ struct { uint32_t *data; /* Raw image data, in ARGB */ @@ -528,6 +532,8 @@ struct terminal { bool autosize; } image; + bool use_private_palette:1; /* Private mode 1070 */ + unsigned params[5]; /* Collected parameters, for RASTER, COLOR_SPEC */ unsigned param; /* Currently collecting parameter, for RASTER, COLOR_SPEC and REPEAT */ unsigned param_idx; /* Parameters seen */ From 8c44b63938684cbd485fec9965f15f1146e32081 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 17 Feb 2021 21:58:36 +0100 Subject: [PATCH 2/3] sixel: free private color registers on unhook --- sixel.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/sixel.c b/sixel.c index dede6e10..63ce493b 100644 --- a/sixel.c +++ b/sixel.c @@ -50,17 +50,9 @@ sixel_init(struct terminal *term) /* TODO: default palette */ if (term->sixel.use_private_palette) { - if (term->sixel.private_palette == NULL) { - term->sixel.private_palette = xcalloc( - term->sixel.palette_size, sizeof(term->sixel.private_palette[0])); - } else { - /* Private palette - i.e. each sixel starts with a clean palette */ - memset( - term->sixel.private_palette, - 0, - term->sixel.palette_size * sizeof(term->sixel.private_palette[0])); - } - + xassert(term->sixel.private_palette == NULL); + term->sixel.private_palette = xcalloc( + term->sixel.palette_size, sizeof(term->sixel.private_palette[0])); term->sixel.palette = term->sixel.private_palette; } else { if (term->sixel.shared_palette == NULL) { @@ -794,6 +786,9 @@ sixel_unhook(struct terminal *term) term->sixel.max_col = 0; term->sixel.pos = (struct coord){0, 0}; + free(term->sixel.private_palette); + term->sixel.private_palette = NULL; + LOG_DBG("you now have %zu sixels in current grid", tll_length(term->grid->sixel_images)); From 667b3e9a1a027141de246ff1a7751e78405222be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 23 Feb 2021 09:42:14 +0100 Subject: [PATCH 3/3] doc: ctlseq: add private mode 1070 - use private color registers for each sixel --- doc/foot-ctlseqs.5.scd | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/foot-ctlseqs.5.scd b/doc/foot-ctlseqs.5.scd index 49187eb2..9b459507 100644 --- a/doc/foot-ctlseqs.5.scd +++ b/doc/foot-ctlseqs.5.scd @@ -310,6 +310,9 @@ that corresponds to one of the following modes: | 1049 : xterm : Equivalent to 1048 and 1047 combined +| 1070 +: xterm +: Use private color registers for each sixel | 2004 : xterm : Wrap pasted text with start/end delimiters (bracketed paste mode)