Multiple font weights
[ I've just found this draft lying around on my hard drive, and thought I'd publish it rather than delete permanently. I didn't publish it back then when I wrote it because I have doubts about its usefulness. As per the announcement at https://gitlab.gnome.org/GNOME/vte/-/issues/259, I won't be following the comments or engaged in discussions. ]
Terminals traditionally support two font weights: regular and bold (the latter selected using SGR 1).
SGR 1 is ambiguous, though. ECMA-48 says "bold or increased intensity", and many terminal emulators implement it by switching to brighter color, instead of or in addition to making it bold.
Recently, with the emerge of the 256-color palette and direct truecolor support, there's been some effort in cleaning this up and making SGR 1 stand for bold only. See for example https://github.com/kovidgoyal/kitty/issues/197 and https://bugzilla.gnome.org/show_bug.cgi?id=762247.
This trend also raised some questions about SGR 2 "faint, decreased intensity or second colour", see https://bugzilla.gnome.org/show_bug.cgi?id=791596.
In the mean time, "Variable Fonts" is a new effort for the web, and probably eventually for the desktop too. See e.g. https://v-fonts.com/ for a demo of quite few a fonts (including variable versions of the monospace Fira Code and Source Code under a free license) whose weight can be altered continuously by dragging a slider. I find it likely that such fonts, including the required supporting code (e.g. OpenType, Pango etc.) will hit most operating systems in the next couple of years.
Terminal emulators have limited choices when it comes to emphasizing some text (e.g. a header) or demoting one. The most obvious and most prominent choice used on web pages, documents and such, namely to play with the font size, is unavailable due to the grid nature. Bold, italic, underlined text offer a quite limited choice. Playing with colors easily results in too much visual clutter. Offering more font weights could perhaps help here.
There seems to be a common agreement for the weight to range from 1 to 1000, with the value of 400 standing for the regular width, and 700 for bold. This numbering is used at least in the OpenType specification, in CSS and in Pango. I think it would be silly for us to go with something else.
Following the spirit of SGR 4:N for underline styles, introduced recently by Kitty and followed by quite a few other terminals, hereby I propose the following extension and clarification for SGR modes 1, 2 and 22:
SGR 1:N, where N goes from 1 to 1000 inclusive, would set the given weight. Example: SGR 1:1 selects the thinnest available variant, SGR 1:400 selects the regular weight, SGR 1:700 selects bold weight, SGR 1:1000 selects the heaviest one available. Moreover, all these sequences would guarantee not to tamper with the color of the text.
SGR 22, SGR 0, or any other means of resetting the attributes would pick the default weight of 400, that is, be an alias to SGR 1:400. SGR 1:0 would also be alias for these.
SGR 1 could, depending on the terminal emulator's choice and/or the user's preference, either switch to a special "weight" which brightens the foreground color, or use font weight 700 (that is, be an alias to SGR 1:700), or both. Our recommendation is to change to bold only, that is, be an alias to 1:700.
SGR 2 could, depending on the terminal emulator's choice and/or the user's preference, either switch to a special "weight" that turns the foreground color pale, or use a lighter font (for example 200, that is, be an alias to SGR 1:200), or both. Our recommendation is to change to a lighter font only, that is, be an alias to 1:200 (or another nearby number - FIXME should we recommend any of 100, 200 or 300 in particular?).
Let's emphasize again that SGR 1:N, for all values of N from 1 to 1000, would result in a mode where the foreground color is not mangled, that is, only the font weight is influenced. This way, in any terminal supporting this extension, SGR 1:700 could be combined with the first 8 palette colors and the result would guaranteed to be the same dark shades of those colors in bold, even if SGR 1 combined with these colors turns them brighter.
Terminal emulators aren't expected to devote 10 bits of storage per cell for the weight. It is perfectly reasonable to parse the values according to this specification, and round to a supported value. This rounding should probably happen according to CSS Fonts Module Level 4's Font Matching Algorithm – FIXME does this make sense?
Usually only weight values that are multiples of 100, from 100 to 900 are used. These, along with the possible special cases of SGR 1 (weight 700 with brighter colors) and SGR 2 (weight 200 with fainter colors) would result in up to 11 values to support, stored in 4 bits.
A terminal could even decide to further cut it down to 3 or 2 bits of storage. For example, 2 bits could denote the choice between these four options: light (SGR 1:N where N <= 399, and SGR 2), normal (SGR 1:N where 400 <= N <= 500), bold with no color mangling (SGR 1:N where N >= 501), bold with possible color mangling (SGR 1).
Of course, even terminals that only devote 1 bit for this property (support bold but not faint) are welcome to parse and accept these sequences, if they guarantee not to tamper with the color.
FIXME Does it really make sense to go for such fine-grained values? Should we just divide by 100, allow the subparameter to go from 1 to 9 only, corresponding to CSS values 100 to 900 in steps of 100, as in CSS Fonts Module Level 3? On the web, the font and its weight are specified by the same entity. In terminals, the font is configured by the user, and the weight is picked by the application, these two are not tightly coupled. Will we ever need more than 9 weights? On the other hand, saving two bytes doesn't take us anywhere, but will result in a terrible mess if there's ever a need for more fine-grained values.