terminal: modernize color palette

The terminal now got a configurable palette for 16 colors (8 normal, 8
bright/bold).

  <config>
    <palette>
      <color index="0" value="#000000"/> <!-- black is real black -->
      <color index="8" value="#101010"/> <!-- bright black stands out a bit -->
    </palette>
  </config>

Note, the old (undocumented) <color index="..." bg="..."> configuration
scheme is no longer supported.

Also, this commit adds a pleasing default palette that ensures
readability of ViM's standard hightlighting.

Fixes #3406
This commit is contained in:
Christian Helmuth 2019-05-12 15:52:00 +02:00
parent 72478a9e31
commit ae7fbd6b1a
6 changed files with 90 additions and 47 deletions

View File

@ -22,5 +22,5 @@
<default-policy root="/fonts" /> <default-policy root="/fonts" />
<!-- color definition when this file is used as terminal config --> <!-- color definition when this file is used as terminal config -->
<color index="0" bg="#1c2232"/> <palette> <color index="0" value="#1c2232"/> </palette>
</config> </config>

View File

@ -244,8 +244,10 @@
<resource name="RAM" quantum="4M"/> <resource name="RAM" quantum="4M"/>
<provides> <service name="Terminal"/> </provides> <provides> <service name="Terminal"/> </provides>
<config> <config>
<color index="0" bg="#2f3953"/> <palette>
<color index="8" bg="#2f3953"/> <color index="0" value="#2f3953"/>
<color index="8" value="#2f3953"/>
</palette>
<vfs> <vfs>
<rom name="VeraMono.ttf"/> <rom name="VeraMono.ttf"/>
<dir name="fonts"> <dir name="fonts">

View File

@ -956,9 +956,11 @@ void Sculpt::Main::_handle_nitpicker_mode()
xml.node("default-policy", [&] () { xml.attribute("root", "/fonts"); }); xml.node("default-policy", [&] () { xml.attribute("root", "/fonts"); });
auto gen_color = [&] (unsigned index, Color color) { auto gen_color = [&] (unsigned index, Color color) {
xml.node("color", [&] () { xml.node("palette", [&] () {
xml.attribute("index", index); xml.node("color", [&] () {
xml.attribute("bg", String<16>(color)); xml.attribute("index", index);
xml.attribute("value", String<16>(color));
});
}); });
}; };

View File

@ -0,0 +1,19 @@
This is a graphical terminal implementation. It provides the Terminal
service and uses a nitpicker session for screen representation.
Configuration
~~~~~~~~~~~~~
The default color palette can be configured via the <palette> XML
configuration node like follows. There are 16 colors configurable -
index 0-7 normal color and index 8-15 bright (bold) colors.
! <config>
! <palette>
! <color index="0" value="#000000"/> <!-- black is real black -->
! <color index="8" value="#101010"/> <!-- bright black stands out a bit -->
! </palette>
! ...
! </config>

View File

@ -1,11 +1,12 @@
/* /*
* \brief Terminal color palette * \brief Terminal color palette
* \author Norman Feske * \author Norman Feske
* \author Christian Helmuth
* \date 2018-02-06 * \date 2018-02-06
*/ */
/* /*
* Copyright (C) 2018 Genode Labs GmbH * Copyright (C) 2018-2019 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3. * under the terms of the GNU Affero General Public License version 3.
@ -16,6 +17,7 @@
/* Genode includes */ /* Genode includes */
#include <util/color.h> #include <util/color.h>
#include <util/xml_node.h>
/* local includes */ /* local includes */
#include "types.h" #include "types.h"
@ -33,44 +35,61 @@ class Terminal::Color_palette
struct Highlighted { bool value; }; struct Highlighted { bool value; };
struct Inverse { bool value; };
private: private:
enum { NUM_COLORS = 16U }; enum { NUM_COLORS = 16U };
Color _colors[NUM_COLORS]; Color _colors[NUM_COLORS];
static constexpr char const * _default_palette {
"<palette>"
" <color index=\"0\" value=\"#000000\"/>" /* black */
" <color index=\"1\" value=\"#AC4142\"/>" /* red */
" <color index=\"2\" value=\"#90A959\"/>" /* green */
" <color index=\"3\" value=\"#F4BF75\"/>" /* yellow */
" <color index=\"4\" value=\"#6A9FB5\"/>" /* blue */
" <color index=\"5\" value=\"#AA759F\"/>" /* magenta */
" <color index=\"6\" value=\"#75B5AA\"/>" /* cyan */
" <color index=\"7\" value=\"#D0D0D0\"/>" /* white */
" <color index=\"8\" value=\"#101010\"/>" /* bright black */
" <color index=\"9\" value=\"#AC4142\"/>" /* bright red */
" <color index=\"10\" value=\"#90A959\"/>" /* bright green */
" <color index=\"11\" value=\"#F4BF75\"/>" /* bright yellow */
" <color index=\"12\" value=\"#6A9FB5\"/>" /* bright blue */
" <color index=\"13\" value=\"#AA759F\"/>" /* bright magenta */
" <color index=\"14\" value=\"#75B5AA\"/>" /* bright cyan */
" <color index=\"15\" value=\"#F5F5F5\"/>" /* bright white */
"</palette>" };
Genode::Xml_node const _default { _default_palette };
void _apply_palette(Xml_node palette)
{
palette.for_each_sub_node("color", [&] (Xml_node node) {
if (!node.has_attribute("index")) return;
if (!node.has_attribute("value")) return;
unsigned const index = node.attribute_value("index", 0U);
if (!(index <= NUM_COLORS)) return;
_colors[index] = node.attribute_value("value", Color());
});
}
public: public:
Color_palette() Color_palette()
{ {
_colors[0] = Color( 0, 0, 0); /* black */ _apply_palette(_default);
_colors[1] = Color(255, 128, 128); /* red */
_colors[2] = Color(128, 255, 128); /* green */
_colors[3] = Color(255, 255, 0); /* yellow */
_colors[4] = Color(128, 128, 255); /* blue */
_colors[5] = Color(255, 0, 255); /* magenta */
_colors[6] = Color( 0, 255, 255); /* cyan */
_colors[7] = Color(255, 255, 255); /* white */
/* the upper portion of the palette contains highlight colors */
for (unsigned i = 0; i < NUM_COLORS/2; i++) {
Color const col = _colors[i];
_colors[i + NUM_COLORS/2] = Color((col.r*2)/3, (col.g*2)/3, (col.b*2)/3);
}
} }
void apply_config(Xml_node config) void apply_config(Xml_node config)
{ {
config.for_each_sub_node("color", [&] (Xml_node color) { _apply_palette(_default);
unsigned const index = min(color.attribute_value("index", 0U), 15U); if (config.has_sub_node("palette"))
Color const bg = color.attribute_value("bg", Color()); _apply_palette(config.sub_node("palette"));
_colors[index] = bg;
});
} }
Color foreground(Index index, Highlighted highlighted, Inverse inverse) const Color foreground(Index index, Highlighted highlighted) const
{ {
if (index.value >= NUM_COLORS/2) if (index.value >= NUM_COLORS/2)
return Color(0, 0, 0); return Color(0, 0, 0);
@ -78,18 +97,15 @@ class Terminal::Color_palette
Color const col = Color const col =
_colors[index.value + (highlighted.value ? NUM_COLORS/2 : 0)]; _colors[index.value + (highlighted.value ? NUM_COLORS/2 : 0)];
return (inverse.value) ? Color(col.r/2, col.g/2, col.b/2) : col; return col;
} }
Color background(Index index, Highlighted highlighted, Inverse inverse) const Color background(Index index, Highlighted highlighted) const
{ {
Color const color = Color const color = foreground(index, highlighted);
_colors[index.value + (highlighted.value ? NUM_COLORS/2 : 0)];
return (inverse.value) ? Color((color.r + 255)/2, /* reduce the intensity of background colors */
(color.g + 255)/2, return Color(color.r*3/4, color.g*3/4, color.b*3/4);
(color.b + 255)/2)
: color;
} }
}; };

View File

@ -1,6 +1,7 @@
/* /*
* \brief Terminal graphics backend for textual screen * \brief Terminal graphics backend for textual screen
* \author Norman Feske * \author Norman Feske
* \author Christian Helmuth
* \date 2018-02-06 * \date 2018-02-06
*/ */
@ -177,8 +178,7 @@ class Terminal::Text_screen_surface
{ {
Color const bg_color = Color const bg_color =
_palette.background(Color_palette::Index{0}, _palette.background(Color_palette::Index{0},
Color_palette::Highlighted{false}, Color_palette::Highlighted{false});
Color_palette::Inverse{false});
Rect r[4] { }; Rect r[4] { };
Rect const all(Point(0, 0), _geometry.fb_size); Rect const all(Point(0, 0), _geometry.fb_size);
_geometry.fb_rect().cut(_geometry.used_rect(), &r[0], &r[1], &r[2], &r[3]); _geometry.fb_rect().cut(_geometry.used_rect(), &r[0], &r[1], &r[2], &r[3]);
@ -197,20 +197,24 @@ class Terminal::Text_screen_surface
Fixpoint_number x { (int)_geometry.start().x() }; Fixpoint_number x { (int)_geometry.start().x() };
for (unsigned column = 0; column < _cell_array.num_cols(); column++) { for (unsigned column = 0; column < _cell_array.num_cols(); column++) {
Char_cell cell = _cell_array.get_cell(column, line); Char_cell const cell = _cell_array.get_cell(column, line);
_font.apply_glyph(cell.codepoint(), [&] (Glyph_painter::Glyph const &glyph) { _font.apply_glyph(cell.codepoint(), [&] (Glyph_painter::Glyph const &glyph) {
Color_palette::Highlighted const highlighted { cell.highlight() }; Color_palette::Highlighted const highlighted { cell.highlight() };
Color_palette::Inverse const inverse { cell.inverse() };
Color fg_color = Color_palette::Index fg_idx { cell.colidx_fg() };
_palette.foreground(Color_palette::Index{cell.colidx_fg()}, Color_palette::Index bg_idx { cell.colidx_bg() };
highlighted, inverse);
Color bg_color = /* swap color index for inverse cells */
_palette.background(Color_palette::Index{cell.colidx_bg()}, if (cell.inverse()) {
highlighted, inverse); Color_palette::Index tmp { fg_idx };
fg_idx = bg_idx;
bg_idx = tmp;
}
Color fg_color = _palette.foreground(fg_idx, highlighted);
Color bg_color = _palette.background(bg_idx, highlighted);
if (cell.has_cursor()) { if (cell.has_cursor()) {
fg_color = Color( 63, 63, 63); fg_color = Color( 63, 63, 63);