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] 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 */