gbranden pushed a commit to branch master
in repository groff.
commit 9edae43657c222f630eef84e8ab38603071a033f
Author: Deri James <[email protected]>
AuthorDate: Sat May 24 00:08:28 2025 +0000
[grotty]: Add SGR 38/48 high color depth support.
* src/devices/grotty/tty.cpp: Add support for devices supporting
ECMA-48/ISO 6429 SGR 38 and 48 escape sequences for specifying 24-bit
color values in the RGB color space. Add global Boolean variable
`want_sgr_truecolor`.
(class tty_glyph): Promote `back_color_idx` and `fore_color_idx`
member variables from `schar` (signed char) to `long`.
(class tty_printer): Promote `curr_fore_idx` and `curr_back_idx`
member variables from `schar` (signed char) to `long`. Promote return
value of `color_to_idx()` member function from pointer-to-`schar` to
pointer-to-`long`. Promote fourth argument of `has_color()` member
function from pointer-to-`schar` to pointer-to-`long`. Promote first
argument of `put_color()` member function from `schar` to `long`.
(tty_printer::has_color): Promote `idx` argument from pointer-to-
`schar` to pointer-to-`long`. Guard existing color-definition logic
behind test of `want_sgr_truecolor` for falsity; otherwise, compute
`idx` using bitwise shifts and addition.
(tty_printer::tty_printer): Promote `dummy` local variable from
`schar` to `long`.
(tty_printer::color_to_idx): Promote return value from pointer-to-
`schar` to pointer-to-`long`. Promote `idx` local variable from
`schar` to `long`.
(tty_printer::put_color): Promote `color_index` argument from `schar`
to `long`. Guard existing SGR color escape sequence emission logic
(which uses SGR 30-37 and 40-47) behind test of `want_sgr_truecolor`
for falsity; otherwise, emit SGR 38 and 48 sequences.
(main): Recognize new `-t` option to select use of SGR 38 and 48
escape sequences. If specified, configure `want_sgr_truecolor` as
true.
* src/devices/grotty/grotty.1.man (Synopsis, Description, Options):
* src/devices/grotty/tty.cpp (usage): Document new `-t` option.
Fixes <https://savannah.gnu.org/bugs/?67153>.
---
ChangeLog | 40 ++++++++++++++
src/devices/grotty/grotty.1.man | 38 +++++++++++++-
src/devices/grotty/tty.cpp | 114 ++++++++++++++++++++++++----------------
3 files changed, 145 insertions(+), 47 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index d72025bbc..79977bd49 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,43 @@
+2025-05-24 Deri James <[email protected]>
+
+ * src/devices/grotty/tty.cpp: Add support for devices supporting
+ ECMA-48/ISO 6429 SGR 38 and 48 escape sequences for specifying
+ 24-bit color values in the RGB color space. Add global Boolean
+ variable `want_sgr_truecolor`.
+ (class tty_glyph): Promote `back_color_idx` and
+ `fore_color_idx` member variables from `schar` (signed char) to
+ `long`.
+ (class tty_printer): Promote `curr_fore_idx` and `curr_back_idx`
+ member variables from `schar` (signed char) to `long`. Promote
+ return value of `color_to_idx()` member function from
+ pointer-to-`schar` to pointer-to-`long`. Promote fourth
+ argument of `has_color()` member function from
+ pointer-to-`schar` to pointer-to-`long`. Promote first argument
+ of `put_color()` member function from `schar` to `long`.
+ (tty_printer::has_color): Promote `idx` argument from
+ pointer-to-`schar` to pointer-to-`long`. Guard existing
+ color-definition logic behind test of `want_sgr_truecolor` for
+ falsity; otherwise, compute `idx` using bitwise shifts and
+ addition.
+ (tty_printer::tty_printer): Promote `dummy` local variable
+ from `schar` to `long`.
+ (tty_printer::color_to_idx): Promote return value from
+ pointer-to-`schar` to pointer-to-`long`. Promote `idx` local
+ variable from `schar` to `long`.
+ (tty_printer::put_color): Promote `color_index` argument from
+ `schar` to `long`. Guard existing SGR color escape sequence
+ emission logic (which uses SGR 30-37 and 40-47) behind test of
+ `want_sgr_truecolor` for falsity; otherwise, emit SGR 38 and 48
+ sequences.
+ (main): Recognize new `-t` option to select use of SGR 38 and 48
+ escape sequences. If specified, configure `want_sgr_truecolor`
+ as true.
+ * src/devices/grotty/grotty.1.man (Synopsis, Description)
+ (Options):
+ * src/devices/grotty/tty.cpp (usage): Document new `-t` option.
+
+ Fixes <https://savannah.gnu.org/bugs/?67153>.
+
2025-06-03 G. Branden Robinson <[email protected]>
* src/devices/grotty/tty.cpp (class tty_printer): Rename member
diff --git a/src/devices/grotty/grotty.1.man b/src/devices/grotty/grotty.1.man
index eb043d193..edac3db65 100644
--- a/src/devices/grotty/grotty.1.man
+++ b/src/devices/grotty/grotty.1.man
@@ -52,7 +52,7 @@ output driver for typewriter-like (terminal) devices
.\" ====================================================================
.
.SY grotty
-.RB [ \-dfho ]
+.RB [ \-dfhot ]
.RB [ \-i \||\| \-r ]
.RB [ \-F\~\c
.IR font-directory ]
@@ -146,7 +146,7 @@ reverse video
[\[lq]negative image\[rq]]
and colors).
.
-Devices supporting the appropriate sequences can view
+By default, devices supporting the appropriate sequences can view
.I roff
documents using eight different background and foreground colors.
.
@@ -165,6 +165,37 @@ and cyan.
Unrecognized colors are mapped to the default color,
which is dependent on the settings of the terminal.
.
+If
+.B -P-t
+is passed to groff (which sets
+.I grotty's
+.B -t
+flag - see below) it operates in TRUECOLOR mode and any
+RGB colour can be used as foreground and background.
+Many terminal emulators now support the TRUECOLOR extensions
+if your environment includes:-
+.P
+.RS
+COLORTERM="truecolor"
+.RE
+.P
+You specify the RGB colours using the usual:-
+.P
+.RS
+\&.defcolor mediumspringgreen rgb #00fa9a
+.P
+.RE
+NOTE: only rgb colour definitions are supported.
+.P
+And then use \[rs]m[...] and \[rs]M[...] to specify the foreground
+and background colours.
+The 8 legacy, 4 bit, colours (defined above) may look different when
+used with 24 bit colours. The reason is because although tty.tmac
+defines "yellow" as rgb #ffff00, it uses rgb #b26818 (or #e5cb3f for
+text when the bold font is selected), whereas for 24 bit colours the
+full #ffff00 is used, and using the bold font just bolds the text
+rather than alter the colour.
+.P
OSC\~8 hyperlinks are produced for these devices.
.
.
@@ -587,6 +618,9 @@ is also specified.
.
.
.TP
+.B \-t
+Use 24 bit "TRUECOLOR" extension rather than 4 bit legacy colours.
+.TP
.B \-u
Suppress the use of underlining for italic characters in legacy output
format.
diff --git a/src/devices/grotty/tty.cpp b/src/devices/grotty/tty.cpp
index 92bd22296..c5f8b072a 100644
--- a/src/devices/grotty/tty.cpp
+++ b/src/devices/grotty/tty.cpp
@@ -68,7 +68,7 @@ static bool do_sgr_italics;
static bool want_reverse_video_for_italics = false;
static bool do_reverse_video;
static bool use_overstriking_drawing_scheme = false;
-
+static bool want_sgr_truecolor = false;
static void update_options();
static void usage(FILE *stream);
@@ -169,8 +169,8 @@ public:
int hpos;
unsigned int code;
unsigned char mode;
- schar back_color_idx;
- schar fore_color_idx;
+ long back_color_idx;
+ long fore_color_idx;
inline int draw_mode() { return mode & (VDRAW_MODE|HDRAW_MODE); }
inline int order() {
return mode & (VDRAW_MODE|HDRAW_MODE|CU_MODE|COLOR_CHANGE); }
@@ -182,20 +182,20 @@ class tty_printer : public printer {
int nlines;
int cached_v;
int cached_vpos;
- schar curr_fore_idx;
- schar curr_back_idx;
+ long curr_fore_idx;
+ long curr_back_idx;
bool is_underlining;
bool is_boldfacing;
bool is_continuously_underlining;
PTABLE(schar) tty_colors;
void make_underline(int);
void make_bold(output_character, int);
- schar color_to_idx(color *);
+ long color_to_idx(color *);
void add_char(output_character, int, int, int, color *, color *,
unsigned char);
void simple_add_char(const output_character, const environment *);
char *make_rgb_string(unsigned int, unsigned int, unsigned int);
- bool has_color(unsigned int, unsigned int, unsigned int, schar *,
+ bool has_color(unsigned int, unsigned int, unsigned int, long *,
schar = DEFAULT_COLOR_IDX);
void line(int, int, int, int, color *, color *);
void draw_line(int *, int, const environment *);
@@ -210,7 +210,7 @@ public:
void change_color(const environment * const);
void change_fill_color(const environment * const);
void put_char(output_character);
- void put_color(schar, int);
+ void put_color(long, int);
void begin_page(int) { }
void end_page(int);
font *make_font(const char *);
@@ -240,19 +240,24 @@ char *tty_printer::make_rgb_string(unsigned int r,
bool tty_printer::has_color(unsigned int r,
unsigned int g,
- unsigned int b, schar *idx, schar value)
+ unsigned int b, long *idx, schar value)
{
bool is_known_color = true;
- char *s = make_rgb_string(r, g, b);
- schar *i = tty_colors.lookup(s);
- if (0 /* nullptr */ == i) {
- is_known_color = false;
- i = new schar[1];
- *i = value;
- tty_colors.define(s, i);
+ if (!want_sgr_truecolor) {
+ char *s = make_rgb_string(r, g, b);
+ schar *i = tty_colors.lookup(s);
+ if (0 /* nullptr */ == i) {
+ is_known_color = false;
+ i = new schar[1];
+ *i = value;
+ tty_colors.define(s, i);
+ }
+ *idx = *i;
+ delete[] s;
+ }
+ else {
+ *idx=((r>>8)<<16) + ((g>>8)<<8) + (b>>8);
}
- *idx = *i;
- delete[] s;
return is_known_color;
}
@@ -263,7 +268,7 @@ tty_printer::tty_printer() : cached_v(0)
vline_char = 0x2502;
}
// TODO: Skip color setup if terminfo `colors` capability is "-1".
- schar dummy;
+ long dummy;
// Create the eight ANSI X3.64/ECMA-48/ISO 6429 standard colors.
// black, white
(void) has_color(0, 0, 0, &dummy, 0);
@@ -334,13 +339,13 @@ void tty_printer::make_bold(output_character c, int w)
}
}
-schar tty_printer::color_to_idx(color *col)
+long tty_printer::color_to_idx(color *col)
{
if (col->is_default())
return DEFAULT_COLOR_IDX;
unsigned int r, g, b;
col->get_rgb(&r, &g, &b);
- schar idx;
+ long idx;
if (!has_color(r, g, b, &idx)) {
char *s = col->print_color();
error("unsupported color '%1' mapped to default", s);
@@ -702,33 +707,48 @@ void tty_printer::put_char(output_character wc)
putchar(wc);
}
-void tty_printer::put_color(schar color_index, int back)
+void tty_printer::put_color(long color_index, int back)
{
- if (color_index == DEFAULT_COLOR_IDX) {
- putstring(SGR_DEFAULT);
- // set bold and underline again
- if (is_boldfacing)
- putstring(SGR_BOLD);
- if (is_underlining) {
- if (do_sgr_italics)
- putstring(SGR_ITALIC);
- else if (do_reverse_video)
- putstring(SGR_REVERSE);
+ if (!want_sgr_truecolor) {
+ if (color_index == DEFAULT_COLOR_IDX) {
+ putstring(SGR_DEFAULT);
+ // set bold and underline again
+ if (is_boldfacing)
+ putstring(SGR_BOLD);
+ if (is_underlining) {
+ if (do_sgr_italics)
+ putstring(SGR_ITALIC);
+ else if (do_reverse_video)
+ putstring(SGR_REVERSE);
+ else
+ putstring(SGR_UNDERLINE);
+ }
+ // set other color again
+ back = !back;
+ color_index = back ? curr_back_idx : curr_fore_idx;
+ }
+ if (color_index != DEFAULT_COLOR_IDX) {
+ putstring(CSI);
+ if (back)
+ putchar('4');
else
- putstring(SGR_UNDERLINE);
+ putchar('3');
+ putchar(color_index + '0');
+ putchar('m');
}
- // set other color again
- back = !back;
- color_index = back ? curr_back_idx : curr_fore_idx;
}
- if (color_index != DEFAULT_COLOR_IDX) {
+ else {
+ if (color_index == DEFAULT_COLOR_IDX) {
+ putstring(SGR_DEFAULT);
+ back = !back;
+ color_index = back ? curr_back_idx : curr_fore_idx;
+ if (color_index == DEFAULT_COLOR_IDX) {return;}
+ }
putstring(CSI);
- if (back)
- putchar('4');
- else
- putchar('3');
- putchar(color_index + '0');
- putchar('m');
+ int fb = back ? 48 : 38;
+ static char buf[24];
+ sprintf(buf,"%d;2;%u;%u;%um",fb, color_index>>16, (color_index>>8) & 0xff,
color_index & 0xff);
+ putstring(buf);
}
}
@@ -959,7 +979,7 @@ int main(int argc, char **argv)
{ "version", no_argument, 0, 'v' },
{ NULL, 0, 0, 0 }
};
- while ((c = getopt_long(argc, argv, ":bBcdfF:hiI:oruUv", long_options,
+ while ((c = getopt_long(argc, argv, ":bBcdfF:hiI:ortuUv", long_options,
NULL)) != EOF)
switch(c) {
case 'v':
@@ -1015,6 +1035,10 @@ int main(int argc, char **argv)
// Ignore \D commands.
allow_drawing_commands = false;
break;
+ case 't':
+ // TRUECOLOR
+ want_sgr_truecolor = true;
+ break;
case CHAR_MAX + 1: // --help
usage(stdout);
break;
@@ -1045,7 +1069,7 @@ int main(int argc, char **argv)
static void usage(FILE *stream)
{
fprintf(stream,
-"usage: %s [-dfho] [-i|-r] [-F font-directory] [file ...]\n"
+"usage: %s [-dfhot] [-i|-r] [-F font-directory] [file ...]\n"
"usage: %s -c [-bBdfhouU] [-F font-directory] [file ...]\n"
"usage: %s {-v | --version}\n"
"usage: %s --help\n",
_______________________________________________
groff-commit mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/groff-commit