diff --git a/repos/demo/include/scout/canvas.h b/repos/demo/include/scout/canvas.h index eee0154a94..0c52658b88 100644 --- a/repos/demo/include/scout/canvas.h +++ b/repos/demo/include/scout/canvas.h @@ -145,7 +145,7 @@ class Scout::Canvas : public Canvas_base { Texture const &texture = static_cast const &>(texture_base); - Texture_painter::paint(_surface, texture, Color(0, 0, 0), pos, + Texture_painter::paint(_surface, texture, Color::black(), pos, Texture_painter::SOLID, true); } diff --git a/repos/demo/include/scout_gfx/sky_texture_painter.h b/repos/demo/include/scout_gfx/sky_texture_painter.h index 1973c4c1eb..712c38b39d 100644 --- a/repos/demo/include/scout_gfx/sky_texture_painter.h +++ b/repos/demo/include/scout_gfx/sky_texture_painter.h @@ -182,10 +182,10 @@ struct Sky_texture_painter _multiply_buf(_bufs[2][0], TW*TH, 16*16*256); /* create color table */ - _create_coltab(_coltab, Color(255, 255, 255), - Color( 0, 0, 0), - Color(255, 255, 255), - Color( 80, 88, 112)); + _create_coltab(_coltab, Color::rgb(255, 255, 255), + Color::rgb( 0, 0, 0), + Color::rgb(255, 255, 255), + Color::rgb( 80, 88, 112)); /* create fallback texture */ _compose(_fallback[0], TW, TH, 0, TW - 1, diff --git a/repos/demo/src/app/launchpad/launchpad_window.h b/repos/demo/src/app/launchpad/launchpad_window.h index 3bab5a03d4..e009ab0c90 100644 --- a/repos/demo/src/app/launchpad/launchpad_window.h +++ b/repos/demo/src/app/launchpad/launchpad_window.h @@ -110,7 +110,7 @@ class Launchpad_window : public Scout::Scrollbar_listener, Parent_element::draw(canvas, abs_position); /* border */ - Color color(0, 0, 0); + Color const color = Color::black(); canvas.draw_box(0, 0, _size.w(), 1, color); canvas.draw_box(0, _size.h() - 1, _size.w(), 1, color); canvas.draw_box(0, 1, 1, _size.h() - 2, color); diff --git a/repos/demo/src/app/scout/browser_window.cc b/repos/demo/src/app/scout/browser_window.cc index 9a96fb5cdf..70eb5c91c4 100644 --- a/repos/demo/src/app/scout/browser_window.cc +++ b/repos/demo/src/app/scout/browser_window.cc @@ -65,11 +65,11 @@ static unsigned char *glow_icon_gfx[] = { /* color definitions for glowing effect of the icons */ static Color glow_icon_col[] = { - Color(210, 210, 0), - Color( 0, 0, 160), - Color( 0, 0, 160), - Color( 0, 160, 0), - Color(160, 0, 0), + Color::rgb(210, 210, 0), + Color::rgb( 0, 0, 160), + Color::rgb( 0, 0, 160), + Color::rgb( 0, 160, 0), + Color::rgb(160, 0, 0), }; diff --git a/repos/demo/src/app/scout/browser_window.h b/repos/demo/src/app/scout/browser_window.h index 7490399033..178831f78b 100644 --- a/repos/demo/src/app/scout/browser_window.h +++ b/repos/demo/src/app/scout/browser_window.h @@ -145,7 +145,7 @@ class Scout::Browser_window : public Scrollbar_listener, Parent_element::draw(canvas, abs_position); if (_attr & ATTR_BORDER) { - Color color(0, 0, 0); + Color color = Color::black(); canvas.draw_box(0, 0, _size.w(), 1, color); canvas.draw_box(0, _size.h() - 1, _size.w(), 1, color); canvas.draw_box(0, 1, 1, _size.h() - 2, color); diff --git a/repos/demo/src/app/scout/elements.cc b/repos/demo/src/app/scout/elements.cc index 71784903c3..b35dc86e52 100644 --- a/repos/demo/src/app/scout/elements.cc +++ b/repos/demo/src/app/scout/elements.cc @@ -226,8 +226,8 @@ Token::Token(Style *style, const char *str, size_t len) _str(str), _len(len), _style(style), - _col(_style ? _style->color : Color(0, 0, 0)), - _outline(Color(0, 0, 0, 0)) + _col(_style ? _style->color : Color::black()), + _outline(Color{}) { _flags.takes_focus = 0; diff --git a/repos/demo/src/app/scout/elements.h b/repos/demo/src/app/scout/elements.h index 04385db2ad..4ac827aead 100644 --- a/repos/demo/src/app/scout/elements.h +++ b/repos/demo/src/app/scout/elements.h @@ -169,13 +169,13 @@ class Scout::Link_token : public Token, private Link, public Event_handler, { _outline = Color(_style->color.r, _style->color.g, - _style->color.b, _curr_value); + _style->color.b, Color::channel_t(_curr_value)); Token::draw(canvas, abs_position); canvas.draw_box(_position.x() + abs_position.x(), _position.y() + abs_position.y() + _size.h() - 1, - _size.w(), 1, Color(0,0,255)); + _size.w(), 1, Color::rgb(0,0,255)); } void mfocus(bool flag) override diff --git a/repos/demo/src/app/scout/navbar.cc b/repos/demo/src/app/scout/navbar.cc index 7cb84b3f2a..842a08dae0 100644 --- a/repos/demo/src/app/scout/navbar.cc +++ b/repos/demo/src/app/scout/navbar.cc @@ -204,7 +204,7 @@ int Navbar::on_tick() prev_icon->alpha(_curr_value); next_icon->alpha(_curr_value); - navbar_style.color = Color(0, 0, 0, _curr_value); + navbar_style.color = Color { 0, 0, 0, Color::channel_t(_curr_value) }; refresh(); return 1; diff --git a/repos/demo/src/app/scout/styles.h b/repos/demo/src/app/scout/styles.h index 4b5240c61a..6b80d790a0 100644 --- a/repos/demo/src/app/scout/styles.h +++ b/repos/demo/src/app/scout/styles.h @@ -42,21 +42,21 @@ namespace Scout { static Tff_font &title_font = subsection_font; - static Color default_color { 0, 0, 0 }; - static Color text_color { 20, 20, 20 }; - static Color verbatim_bgcol { 0, 0, 0, 26 }; + static constexpr Color default_color = Color::rgb( 0, 0, 0 ); + static constexpr Color text_color = Color::rgb( 20, 20, 20 ); + static constexpr Color verbatim_bgcol { 0, 0, 0, 26 }; static Style plain_style { &default_font, text_color, 0 }; static Style bold_style { &default_font, text_color, Style::ATTR_BOLD }; static Style mono_style { &mono_font, text_color, 0 }; static Style italic_style { &italic_font, text_color, 0 }; - static Style link_style { &default_font, Color(0, 0, 255), 0 }; + static Style link_style { &default_font, Color::rgb(0, 0, 255), 0 }; static Style chapter_style { &chapter_font, default_color, 0 }; static Style section_style { §ion_font, default_color, 0 }; static Style subsection_style { &subsection_font, default_color, 0 }; - static Style navbar_style { &default_font, Color(0, 0, 0, 127), 0 }; + static Style navbar_style { &default_font, Color { 0, 0, 0, 127 }, 0 }; } #endif /* _STYLES_H_ */ diff --git a/repos/demo/src/server/liquid_framebuffer/framebuffer_window.h b/repos/demo/src/server/liquid_framebuffer/framebuffer_window.h index c6ca959e3b..e38a1c5d14 100644 --- a/repos/demo/src/server/liquid_framebuffer/framebuffer_window.h +++ b/repos/demo/src/server/liquid_framebuffer/framebuffer_window.h @@ -224,7 +224,7 @@ class Framebuffer_window : public Scout::Window Parent_element::draw(canvas, abs_position); /* border */ - Color color(0, 0, 0); + Color const color = Color::black(); canvas.draw_box(0, 0, _size.w(), 1, color); if (_config_decoration) canvas.draw_box(0, _TH, _size.w(), 1, color); diff --git a/repos/demo/src/server/nitlog/main.cc b/repos/demo/src/server/nitlog/main.cc index cc2f235e46..c6b213e736 100644 --- a/repos/demo/src/server/nitlog/main.cc +++ b/repos/demo/src/server/nitlog/main.cc @@ -148,12 +148,12 @@ class Log_entry */ void draw(Canvas_base &canvas, Font const &font, int y, int new_section = false) { - Color label_fgcol = Color(Genode::min(255, _color.r + 200), - Genode::min(255, _color.g + 200), - Genode::min(255, _color.b + 200)); - Color label_bgcol = Color(_color.r, _color.g, _color.b); - Color text_fgcol = Color(180, 180, 180); - Color text_bgcol = Color(_color.r / 2, _color.g / 2, _color.b / 2); + Color label_fgcol = Color::clamped_rgb(_color.r + 200, + _color.g + 200, + _color.b + 200); + Color label_bgcol = _color; + Color text_fgcol = Color::rgb(180, 180, 180); + Color text_bgcol = Color::rgb(_color.r / 2, _color.g / 2, _color.b / 2); /* calculate label dimensions */ int label_w = font.string_width(_label).decimal(); @@ -162,11 +162,11 @@ class Log_entry if (new_section) { canvas.draw_box(Rect(Point(1, y), Area(label_w + 2, label_h - 1)), label_bgcol); canvas.draw_string(Point(1, y - 1), font, label_fgcol, _label); - canvas.draw_box(Rect(Point(1, y + label_h - 1), Area(label_w + 2, 1)), Color(0, 0, 0)); + canvas.draw_box(Rect(Point(1, y + label_h - 1), Area(label_w + 2, 1)), Color::black()); canvas.draw_box(Rect(Point(label_w + 2, y), Area(1, label_h - 1)), _color); - canvas.draw_box(Rect(Point(label_w + 3, y), Area(1, label_h - 1)), Color(0, 0, 0)); + canvas.draw_box(Rect(Point(label_w + 3, y), Area(1, label_h - 1)), Color::black()); canvas.draw_box(Rect(Point(label_w + 4, y), Area(1000, label_h)), text_bgcol); - canvas.draw_box(Rect(Point(label_w + 4, y), Area(1000, 1)), Color(0, 0, 0)); + canvas.draw_box(Rect(Point(label_w + 4, y), Area(1000, 1)), Color::black()); } else canvas.draw_box(Rect(Point(1, y), Area(1000, label_h)), text_bgcol); @@ -282,7 +282,7 @@ class Nitlog::Session_component : public Rpc_object int g = (_bit(id, 4) + 2*_bit(id, 1))*scale + offset; int b = (_bit(id, 5) + 2*_bit(id, 2))*scale + offset; - return Color(r, g, b); + return Color::clamped_rgb(r, g, b); } Color const _color = _session_color(_id); diff --git a/repos/gems/include/gems/color_hsv.h b/repos/gems/include/gems/color_hsv.h index aab713cd18..08e3b8306b 100644 --- a/repos/gems/include/gems/color_hsv.h +++ b/repos/gems/include/gems/color_hsv.h @@ -25,7 +25,7 @@ static inline Genode::Color color_from_hsv(unsigned h, unsigned s, unsigned v) using uint8_t = Genode::uint8_t; if (s == 0) - return Color(v, v, v); + return Color::clamped_rgb(v, v, v); uint8_t const region = (uint8_t)(h / 43); uint8_t const remainder = (uint8_t)((h - (region*43)) * 6); @@ -34,14 +34,14 @@ static inline Genode::Color color_from_hsv(unsigned h, unsigned s, unsigned v) t = (uint8_t)((v*(255 - ((s*(255 - remainder)) >> 8))) >> 8); switch (region) { - case 0: return Color(v, t, p); - case 1: return Color(q, v, p); - case 2: return Color(p, v, t); - case 3: return Color(p, q, v); - case 4: return Color(t, p, v); + case 0: return Color::clamped_rgb(v, t, p); + case 1: return Color::clamped_rgb(q, v, p); + case 2: return Color::clamped_rgb(p, v, t); + case 3: return Color::clamped_rgb(p, q, v); + case 4: return Color::clamped_rgb(t, p, v); } - return Color(v, p, q); + return Color::clamped_rgb(v, p, q); } #endif /* _INCLUDE__GEMS__COLOR_HSV_H_ */ diff --git a/repos/gems/include/polygon_gfx/shaded_polygon_painter.h b/repos/gems/include/polygon_gfx/shaded_polygon_painter.h index 6aff7156ea..0234c6db8b 100644 --- a/repos/gems/include/polygon_gfx/shaded_polygon_painter.h +++ b/repos/gems/include/polygon_gfx/shaded_polygon_painter.h @@ -58,14 +58,14 @@ class Polygon::Shaded_painter : public Polygon::Painter_base } } - inline void edge_attr(int id, int value) + inline void edge_attr(int id, auto value) { switch (id) { case ATTR_X: Point_base::edge_attr(id, value); return; - case ATTR_R: color.r = value; return; - case ATTR_G: color.g = value; return; - case ATTR_B: color.b = value; return; - case ATTR_A: color.a = value; return; + case ATTR_R: color.r = Color::channel_t(value); return; + case ATTR_G: color.g = Color::channel_t(value); return; + case ATTR_B: color.b = Color::channel_t(value); return; + case ATTR_A: color.a = Color::channel_t(value); return; } } }; @@ -123,8 +123,8 @@ class Polygon::Shaded_painter : public Polygon::Painter_base for (int y = bbox.y1(); y < bbox.y2(); y++) { /* read left and right color values from corresponding edge buffers */ - Color l_color = Color(r_l_edge[y], g_l_edge[y], b_l_edge[y], a_l_edge[y]); - Color r_color = Color(r_r_edge[y], g_r_edge[y], b_r_edge[y], a_r_edge[y]); + Color l_color = Color::clamped_rgba(r_l_edge[y], g_l_edge[y], b_l_edge[y], a_l_edge[y]); + Color r_color = Color::clamped_rgba(r_r_edge[y], g_r_edge[y], b_r_edge[y], a_r_edge[y]); int const x_l = x_l_edge[y]; int const x_r = x_r_edge[y]; diff --git a/repos/gems/src/app/backdrop/main.cc b/repos/gems/src/app/backdrop/main.cc index de00fa8aa6..5e533e7575 100644 --- a/repos/gems/src/app/backdrop/main.cc +++ b/repos/gems/src/app/backdrop/main.cc @@ -303,7 +303,7 @@ void Backdrop::Main::_apply_fill(Xml_node operation) /* create texture with down-sampled scaled image */ typedef Pixel_rgb888 PT; - Color const color = operation.attribute_value("color", Color(0, 0, 0)); + Color const color = operation.attribute_value("color", Color::black()); _buffer->apply_to_surface([&] (Surface &surface) { Box_painter::paint(surface, Surface_base::Rect(Surface_base::Point(0, 0), diff --git a/repos/gems/src/app/decorator/config.h b/repos/gems/src/app/decorator/config.h index 3b0a6da96f..771e4d00fb 100644 --- a/repos/gems/src/app/decorator/config.h +++ b/repos/gems/src/app/decorator/config.h @@ -164,7 +164,7 @@ class Decorator::Config */ Color base_color(Window_title const &title) const { - Color result(68, 75, 95); + Color result = Color::rgb(68, 75, 95); try { Genode::Session_policy policy(title, _buffered_config->xml()); diff --git a/repos/gems/src/app/decorator/window.cc b/repos/gems/src/app/decorator/window.cc index 5895388cf4..23c1e10069 100644 --- a/repos/gems/src/app/decorator/window.cc +++ b/repos/gems/src/app/decorator/window.cc @@ -187,10 +187,11 @@ void Decorator::Window::draw(Decorator::Canvas_base &canvas, canvas.draw_text(text_pos + Point(1, 1), default_font(), Color(0, 0, 0, 128), text); - Color title_color = element(Element::TITLE).color(); + Color const title_color = element(Element::TITLE).color(); + auto const alpha = Genode::uint8_t((2*255 + title_color.r) / 3); canvas.draw_text(text_pos, default_font(), - Color(255, 255, 255, (2*255 + title_color.r) / 3), text); + Color { 255, 255, 255, alpha }, text); } } diff --git a/repos/gems/src/app/decorator/window.h b/repos/gems/src/app/decorator/window.h index abf8b4a9e3..23e077ec70 100644 --- a/repos/gems/src/app/decorator/window.h +++ b/repos/gems/src/app/decorator/window.h @@ -270,9 +270,12 @@ class Decorator::Window : public Window_base static Color _mix_colors(Color c1, Color c2, int alpha) { - return Color((c1.r*alpha + c2.r*(255 - alpha)) >> 8, - (c1.g*alpha + c2.g*(255 - alpha)) >> 8, - (c1.b*alpha + c2.b*(255 - alpha)) >> 8); + auto mix = [&] (auto const v1, auto const v2) + { + return Genode::uint8_t((v1*alpha + v2*(255 - alpha)) >> 8); + }; + + return Color::rgb(mix(c1.r, c2.r), mix(c1.g, c2.g), mix(c1.b, c2.b)); } void _draw_title_box(Canvas_base &canvas, Rect rect, Attr attr) const @@ -289,8 +292,10 @@ class Decorator::Window : public Window_base int const mid_y = rect.h() / 2; - Color const upper_color = attr.pressed ? Color(0, 0, 0) : Color(255, 255, 255); - Color const lower_color = attr.pressed ? Color(127, 127, 127) : Color(0, 0, 0); + Color const upper_color = attr.pressed ? Color::black() + : Color::rgb(255, 255, 255); + Color const lower_color = attr.pressed ? Color::rgb(127, 127, 127) + : Color::black(); for (unsigned i = 0; i < rect.h(); i++) { @@ -376,7 +381,7 @@ class Decorator::Window : public Window_base case Control::TYPE_TITLE: return _window_elem_attr(Element::TITLE); case Control::TYPE_UNDEFINED: break; }; - return Attr { .color = Color(0, 0, 0), .pressed = false }; + return Attr { .color = Color::black(), .pressed = false }; } Texture_id _window_control_texture(Control window_control) const diff --git a/repos/gems/src/app/decorator/window_element.h b/repos/gems/src/app/decorator/window_element.h index a4826e918c..6865fb5f17 100644 --- a/repos/gems/src/app/decorator/window_element.h +++ b/repos/gems/src/app/decorator/window_element.h @@ -55,16 +55,12 @@ class Decorator::Window_element : public Animator::Item static Color _add(Color c1, Color c2) { - return Color(Genode::min(c1.r + c2.r, 255), - Genode::min(c1.g + c2.g, 255), - Genode::min(c1.b + c2.b, 255)); + return Color::clamped_rgb(c1.r + c2.r, c1.g + c2.g, c1.b + c2.b); } static Color _sub(Color c1, Color c2) { - return Color(Genode::max(c1.r - c2.r, 0), - Genode::max(c1.g - c2.g, 0), - Genode::max(c1.b - c2.b, 0)); + return Color::clamped_rgb(c1.r - c2.r, c1.g - c2.g, c1.b - c2.b); } Type const _type; @@ -83,13 +79,13 @@ class Decorator::Window_element : public Animator::Item Color result = state.base_color; if (state.focused) - result = _add(result, Color(70, 70, 70)); + result = _add(result, Color::rgb(70, 70, 70)); if (state.highlighted) - result = _add(result, Color(65, 60, 55)); + result = _add(result, Color::rgb(65, 60, 55)); if (state.pressed) - result = _sub(result, Color(10, 10, 10)); + result = _sub(result, Color::rgb(10, 10, 10)); return result; } @@ -145,7 +141,7 @@ class Decorator::Window_element : public Animator::Item return ""; } - Color color() const { return Color(_r >> 4, _g >> 4, _b >> 4); } + Color color() const { return Color::clamped_rgb(_r >> 4, _g >> 4, _b >> 4); } /** * \return true if state has changed diff --git a/repos/gems/src/app/menu_view/animated_color.h b/repos/gems/src/app/menu_view/animated_color.h index 0531eb9d6a..83332bff44 100644 --- a/repos/gems/src/app/menu_view/animated_color.h +++ b/repos/gems/src/app/menu_view/animated_color.h @@ -69,7 +69,7 @@ class Genode::Animated_color : private Animator::Item, Noncopyable } } - int value() const { return _value >> 10; } + uint8_t value() const { return uint8_t(_value >> 10); } }; Animated_channel _r { }, _g { }, _b { }, _a { }; @@ -85,7 +85,7 @@ class Genode::Animated_color : private Animator::Item, Noncopyable { _r.animate(); _g.animate(); _b.animate(); _a.animate(); - _color = Color(_r.value(), _g.value(), _b.value(), _a.value()); + _color = Color { _r.value(), _g.value(), _b.value(), _a.value() }; /* schedule / de-schedule animation */ Animator::Item::animated(_r.animated() || _g.animated() || diff --git a/repos/gems/src/app/menu_view/depgraph_widget.h b/repos/gems/src/app/menu_view/depgraph_widget.h index fecf664e26..ee45ecc377 100644 --- a/repos/gems/src/app/menu_view/depgraph_widget.h +++ b/repos/gems/src/app/menu_view/depgraph_widget.h @@ -670,12 +670,14 @@ struct Menu_view::Depgraph_widget : Widget Color color; + auto dimmed_alpha = [&] (uint8_t s) { return uint8_t((s*alpha) >> 8); }; + if (shadow) { - color = dep.primary() ? Color(0, 0, 0, (150*alpha)>>8) - : Color(0, 0, 0, (50*alpha)>>8); + color = dep.primary() ? Color { 0, 0, 0, dimmed_alpha(150) } + : Color { 0, 0, 0, dimmed_alpha(50) }; } else { - color = dep.primary() ? Color(255, 255, 255, (190*alpha)>>8) - : Color(255, 255, 255, (120*alpha)>>8); + color = dep.primary() ? Color { 255, 255, 255, dimmed_alpha(190) } + : Color { 255, 255, 255, dimmed_alpha(120) }; } dep.apply_to_server([&] (Node const &server) { diff --git a/repos/gems/src/app/menu_view/label_widget.h b/repos/gems/src/app/menu_view/label_widget.h index 3731c5b638..0bf6209fb4 100644 --- a/repos/gems/src/app/menu_view/label_widget.h +++ b/repos/gems/src/app/menu_view/label_widget.h @@ -132,8 +132,8 @@ struct Menu_view::Label_widget : Widget, Cursor::Glyph_position _selections.for_each([&] (Text_selection const &selection) { selection.draw(pixel_surface, alpha_surface, at, text_size.h()); }); - Color const color = _color.color(); - int const alpha = color.a; + Color const color = _color.color(); + uint8_t const alpha = color.a; if (alpha) { Text_painter::paint(pixel_surface, diff --git a/repos/gems/src/app/menu_view/style_database.h b/repos/gems/src/app/menu_view/style_database.h index b0114655a5..4c3f7e5363 100644 --- a/repos/gems/src/app/menu_view/style_database.h +++ b/repos/gems/src/app/menu_view/style_database.h @@ -71,7 +71,7 @@ class Menu_view::Style_database Directory const &styles_dir, Path const &path) { - Label_style result { .color = Color(0, 0, 0) }; + Label_style result { .color = Color::black() }; try { File_content const content(alloc, styles_dir, path, diff --git a/repos/gems/src/app/nano3d/main.cc b/repos/gems/src/app/nano3d/main.cc index 06004e07c4..7bfa5c0975 100644 --- a/repos/gems/src/app/nano3d/main.cc +++ b/repos/gems/src/app/nano3d/main.cc @@ -189,8 +189,8 @@ class Scene : public Nano3d::Scene : points[i]; Color const color = - backward_facing ? Color(i*10, i*10, i*10, 230 - i*18) - : Color(240, 10*i, 0, 10 + i*35); + backward_facing ? Color::clamped_rgba(i*10, i*10, i*10, 230 - i*18) + : Color::clamped_rgba(240, 10*i, 0, 10 + i*35); point = Shaded_point(v.x(), v.y(), color); } diff --git a/repos/gems/src/app/osci/main.cc b/repos/gems/src/app/osci/main.cc index 4ad0c0f92c..4aa6fe99d1 100644 --- a/repos/gems/src/app/osci/main.cc +++ b/repos/gems/src/app/osci/main.cc @@ -123,8 +123,8 @@ struct Osci::Main Xml_node const config = _config.xml(); _size = Area::from_xml(config); - _background = config.attribute_value("background", Color { 0, 0, 0 }); - _color = config.attribute_value("color", Color { 255, 255, 255 }); + _background = config.attribute_value("background", Color::black()); + _color = config.attribute_value("color", Color::rgb(255, 255, 255)); _v_scale = config.attribute_value("v_scale", 3000); _gui_buffer.construct(_gui, _size, _env.ram(), _env.rm(), diff --git a/repos/gems/src/app/rom_osci/main.cc b/repos/gems/src/app/rom_osci/main.cc index 7b896b7d3e..7e639c0593 100644 --- a/repos/gems/src/app/rom_osci/main.cc +++ b/repos/gems/src/app/rom_osci/main.cc @@ -216,7 +216,7 @@ struct Osci::Main int const y_pos = int(_attr.v_pos*area.h()); double const screen_v_scale = _attr.v_scale*area.h()/2; - auto _horizontal_line = [&] (Color c, int y, int alpha) + auto _horizontal_line = [&] (Color c, int y, Color::channel_t alpha) { _line_painter.paint(pixel, Point { 0, y }, Point { int(w) - 2, y }, @@ -270,7 +270,7 @@ struct Osci::Main Xml_node const config = _config.xml(); _size = Area::from_xml(config); - _background = config.attribute_value("background", Color { 0, 0, 0 }); + _background = config.attribute_value("background", Color::black()); _fps = config.attribute_value("fps", 50u); _phase_lock = config.attribute_value("phase_lock", false); @@ -280,7 +280,7 @@ struct Osci::Main Channel::Attr const channel_defaults = Channel::Attr::from_xml(config, { .v_pos = 0.5, .v_scale = 0.6, - .color = { 255, 255, 255 }, + .color = Color::rgb(255, 255, 255), }); _gui_buffer.construct(_gui, _size, _env.ram(), _env.rm(), diff --git a/repos/gems/src/app/screenshot_trigger/main.cc b/repos/gems/src/app/screenshot_trigger/main.cc index 5bd6b8b3c0..b1bc8d9dbc 100644 --- a/repos/gems/src/app/screenshot_trigger/main.cc +++ b/repos/gems/src/app/screenshot_trigger/main.cc @@ -40,7 +40,7 @@ struct Screenshot_trigger::Main Point _position { }; Area _area { }; - Color const _color { 200, 0, 0 }; + Color const _color = Color::rgb(200, 0, 0); Input::Keycode const _keycode = Input::KEY_PRINT; diff --git a/repos/gems/src/app/sculpt_manager/main.cc b/repos/gems/src/app/sculpt_manager/main.cc index 24f29ed153..73347d4b4a 100644 --- a/repos/gems/src/app/sculpt_manager/main.cc +++ b/repos/gems/src/app/sculpt_manager/main.cc @@ -2004,7 +2004,7 @@ void Sculpt::Main::_handle_gui_mode() }); }; - Color const background(0x1c, 0x22, 0x32); + Color const background = Color::rgb(0x1c, 0x22, 0x32); gen_color(0, background); gen_color(8, background); diff --git a/repos/gems/src/app/themed_decorator/config.h b/repos/gems/src/app/themed_decorator/config.h index fffd76e981..543b8a33ed 100644 --- a/repos/gems/src/app/themed_decorator/config.h +++ b/repos/gems/src/app/themed_decorator/config.h @@ -67,7 +67,7 @@ class Decorator::Config */ Color base_color(Window_title const &title) const { - Color result(0, 0, 0); + Color result = Color::black(); try { Genode::Session_policy policy(title, _config); diff --git a/repos/gems/src/app/themed_decorator/theme.cc b/repos/gems/src/app/themed_decorator/theme.cc index 7c3bb785bb..5ed274210c 100644 --- a/repos/gems/src/app/themed_decorator/theme.cc +++ b/repos/gems/src/app/themed_decorator/theme.cc @@ -277,7 +277,7 @@ void Decorator::Theme::draw_title(Decorator::Pixel_surface &pixel_surface, Point const pos = title_rect.center(label_area) - Point(0, 1); Text_painter::paint(pixel_surface, Text_painter::Position(pos.x(), pos.y()), - font, Genode::Color(0, 0, 0), title); + font, Color::black(), title); } diff --git a/repos/gems/src/app/themed_decorator/tint_painter.h b/repos/gems/src/app/themed_decorator/tint_painter.h index 6c052fa6c8..d632f10d23 100644 --- a/repos/gems/src/app/themed_decorator/tint_painter.h +++ b/repos/gems/src/app/themed_decorator/tint_painter.h @@ -48,11 +48,11 @@ struct Tint_painter unsigned const lut_idx = color.r + color.g + color.b; - Polygon::interpolate_rgba(Polygon::Color(0, 0, 0), color, + Polygon::interpolate_rgba(Polygon::Color::black(), color, pixel_lut, alpha_lut, lut_idx + 1, 0, 0); - Polygon::interpolate_rgba(color, Polygon::Color(255, 255, 255), + Polygon::interpolate_rgba(color, Polygon::Color::rgb(255, 255, 255), pixel_lut + lut_idx, alpha_lut + lut_idx, LUT_SIZE - lut_idx, 0, 0); diff --git a/repos/gems/src/app/themed_decorator/window.h b/repos/gems/src/app/themed_decorator/window.h index d4b07b1361..d73e90c367 100644 --- a/repos/gems/src/app/themed_decorator/window.h +++ b/repos/gems/src/app/themed_decorator/window.h @@ -230,7 +230,7 @@ class Decorator::Window : public Window_base, public Animator::Item */ Lazy_value _r { }, _g { }, _b { }; - Color _color() const { return Color(_r >> 4, _g >> 4, _b >> 4); } + Color _color() const { return Color::clamped_rgb(_r >> 4, _g >> 4, _b >> 4); } bool _show_decoration = _config.show_decoration(_title); @@ -293,7 +293,7 @@ class Decorator::Window : public Window_base, public Animator::Item _theme.draw_element(pixel, alpha, area, element.type, element.alpha); }); Color const tint_color = _color(); - if (tint_color != Color(0, 0, 0)) + if (tint_color != Color::black()) Tint_painter::paint(pixel, Rect(Point(0, 0), area), tint_color); }); diff --git a/repos/gems/src/server/gui_fader/main.cc b/repos/gems/src/server/gui_fader/main.cc index 655259fdf0..8ec72db4b3 100644 --- a/repos/gems/src/server/gui_fader/main.cc +++ b/repos/gems/src/server/gui_fader/main.cc @@ -171,7 +171,7 @@ class Gui_fader::Framebuffer_session_component Texture_painter::paint(_dst_buffer->pixel_surface(), _src_buffer.texture(), - Genode::Color(0, 0, 0), + Genode::Color::black(), Point(0, 0), Texture_painter::SOLID, false); diff --git a/repos/gems/src/server/terminal/color_palette.h b/repos/gems/src/server/terminal/color_palette.h index 7f82fed4b2..e4f099d087 100644 --- a/repos/gems/src/server/terminal/color_palette.h +++ b/repos/gems/src/server/terminal/color_palette.h @@ -92,7 +92,7 @@ class Terminal::Color_palette Color foreground(Index index, Highlighted highlighted) const { if (index.value >= NUM_COLORS/2) - return Color(0, 0, 0); + return Color::black(); Color const col = _colors[index.value + (highlighted.value ? NUM_COLORS/2 : 0)]; @@ -105,7 +105,7 @@ class Terminal::Color_palette Color const color = foreground(index, highlighted); /* reduce the intensity of background colors */ - return Color(color.r*3/4, color.g*3/4, color.b*3/4); + return Color::clamped_rgb(color.r*3/4, color.g*3/4, color.b*3/4); } }; diff --git a/repos/gems/src/server/terminal/text_screen_surface.h b/repos/gems/src/server/terminal/text_screen_surface.h index 0623da2911..b094087434 100644 --- a/repos/gems/src/server/terminal/text_screen_surface.h +++ b/repos/gems/src/server/terminal/text_screen_surface.h @@ -268,18 +268,18 @@ class Terminal::Text_screen_surface Color bg_color = _palette.background(bg_idx, highlighted); if (selected) { - bg_color = Color(180, 180, 180); - fg_color = Color( 50, 50, 50); + bg_color = Color::rgb(180, 180, 180); + fg_color = Color::rgb( 50, 50, 50); } if (pointer) { - bg_color = Color(220, 220, 220); - fg_color = Color( 50, 50, 50); + bg_color = Color::rgb(220, 220, 220); + fg_color = Color::rgb( 50, 50, 50); } if (cell.has_cursor()) { - fg_color = Color( 63, 63, 63); - bg_color = Color(255, 255, 255); + fg_color = Color::rgb( 63, 63, 63); + bg_color = Color::rgb(255, 255, 255); } PT const pixel(fg_color.r, fg_color.g, fg_color.b); diff --git a/repos/gems/src/test/text_painter/main.cc b/repos/gems/src/test/text_painter/main.cc index dd93ab1640..81e8422a55 100644 --- a/repos/gems/src/test/text_painter/main.cc +++ b/repos/gems/src/test/text_painter/main.cc @@ -86,46 +86,46 @@ struct Test::Main { /* test positioning of text */ _surface.clip(Rect(Point(0, 0), _size)); - Box_painter::paint(_surface, Rect(Point(200, 10), Area(250, 50)), Color(0, 100, 0)); + Box_painter::paint(_surface, Rect(Point(200, 10), Area(250, 50)), Color::rgb(0, 100, 0)); Text_painter::paint(_surface, Text_painter::Position(200, 10), _font_1, - Color(255, 255, 255), + Color::rgb(255, 255, 255), "Text aligned at the top-left corner"); - Box_painter::paint(_surface, Rect(Point(200, 100), Area(250, 50)), Color(0, 100, 0)); + Box_painter::paint(_surface, Rect(Point(200, 100), Area(250, 50)), Color::rgb(0, 100, 0)); Text_painter::paint(_surface, Text_painter::Position(210, (int)(100 - _font_1.baseline())), _font_1, - Color(255, 255, 255), + Color::rgb(255, 255, 255), "Baseline of text aligned at the top"); /* test horizontal clipping boundaries */ _surface.clip(Rect(Point(20, 15), Area(40, 300))); - Box_painter::paint(_surface, Rect(Point(0, 0), _size), Color(150, 20, 10)); + Box_painter::paint(_surface, Rect(Point(0, 0), _size), Color::rgb(150, 20, 10)); for (int x = 0, y = -30; y < (int)_size.h() + 30; x++, y += _font_2.bounding_box().h()) Text_painter::paint(_surface, Text_painter::Position(x, y), _font_2, - Color(255, 255, 255), + Color::rgb(255, 255, 255), "Text painter at work"); /* test horizontal subpixel positioning */ _surface.clip(Rect(Point(90, 15), Area(100, 300))); - Box_painter::paint(_surface, Rect(Point(0, 0), _size), Color(150, 20, 10)); + Box_painter::paint(_surface, Rect(Point(0, 0), _size), Color::rgb(150, 20, 10)); float const font_3_h = (float)_font_3.bounding_box().h(); for (float x = 90, y = -30; y < (float)_size.h() + 30; x += 0.2f, y += font_3_h) Text_painter::paint(_surface, Text_painter::Position(x, y), _font_3, - Color(255, 255, 255), + Color::rgb(255, 255, 255), "This is a real textSub-=_HT-+=%@pixel positioning"); _surface.clip(Rect(Point(90, 320), Area(100, 300))); - Box_painter::paint(_surface, Rect(Point(0, 0), _size), Color(255, 255, 255)); + Box_painter::paint(_surface, Rect(Point(0, 0), _size), Color::rgb(255, 255, 255)); for (float x = 90, y = 300; y < (float)_size.h() + 30; x += 0.2f, y += font_3_h) Text_painter::paint(_surface, Text_painter::Position(x, y), _font_3, - Color(0, 0, 0), + Color::rgb(0, 0, 0), "This is a real textSub-=_HT-+=%@pixel positioning"); _refresh(); @@ -151,7 +151,7 @@ struct Test::Main for (unsigned x = 0; x < 256; x++) Box_painter::paint(_surface, Rect(Point(x + 512, 280 - lut.value[x]), Area(1, 1)), - Color(255, 255, 255)); + Color::rgb(255, 255, 255)); _refresh(); _surface.clip(Rect(Point(0, 0), _size)); @@ -166,7 +166,7 @@ struct Test::Main Text_painter::paint(_surface, Text_painter::Position(260 + (i*133 % 500), 320 + (i*87 % 400)), - _font_4, Color(150 + i*73, 0, 200), + _font_4, Color::clamped_rgb(150 + i*73, 0, 200), "Glyphs obtained from VFS"); Genode::uint64_t const end_us = timer.elapsed_us(); @@ -190,7 +190,7 @@ struct Test::Main Text_painter::paint(_surface, Text_painter::Position(260 + (i*83 % 500), 320 + (i*153 % 400)), - cached_font, Color(30, (int)limit_kib, 150 + i*73), + cached_font, Color::clamped_rgb(30, (int)limit_kib, 150 + i*73), "Glyphs obtained from VFS"); Genode::uint64_t const end_us = timer.elapsed_us(); diff --git a/repos/os/include/decorator/xml_utils.h b/repos/os/include/decorator/xml_utils.h index 73c7ce7859..a565cef3c1 100644 --- a/repos/os/include/decorator/xml_utils.h +++ b/repos/os/include/decorator/xml_utils.h @@ -24,7 +24,7 @@ namespace Decorator { static Color color(Xml_node const &); } */ static inline Genode::Color Decorator::color(Genode::Xml_node const &color) { - return color.attribute_value("color", Color(0, 0, 0)); + return color.attribute_value("color", Color::black()); } #endif /* _INCLUDE__DECORATOR__XML_UTILS_H_ */ diff --git a/repos/os/include/util/color.h b/repos/os/include/util/color.h index b64cbf8a2e..0cff7233b7 100644 --- a/repos/os/include/util/color.h +++ b/repos/os/include/util/color.h @@ -23,35 +23,74 @@ namespace Genode { } +/** + * Tuple of red, green, blue, and alpha color components + */ struct Genode::Color { - int r, g, b, a; + using channel_t = uint8_t; + + channel_t r {}, g {}, b {}, a {}; + + /** + * Construct opaque color + */ + static constexpr Color rgb(uint8_t r, uint8_t g, uint8_t b) + { + return { r, g, b, 255 }; + } + + /** + * Construct color from component values + * + * This function is useful when colors are computed from integer values. + * Whenever a component value lies outside the value range of 'channel_t', + * it is clamped to the minimum/maximum value. + */ + static Color clamped_rgba(auto r, auto g, auto b, auto a) + { + auto clamped = [] (auto const v) + { + return (v < 0) ? uint8_t(0) : (v >= 255) ? uint8_t(255) : uint8_t(v); + }; + + return { clamped(r), clamped(g), clamped(b), clamped(a) }; + } + + /** + * Construct opaque color from component values + */ + static Color clamped_rgb(auto r, auto g, auto b) + { + return clamped_rgba(r, g, b, 255); + } + + /** + * Construct opaque black color + */ + static constexpr Color black() { return rgb(0, 0, 0); } bool opaque() const { return a == 255; } bool transparent() const { return a == 0; } - Color(int red, int green, int blue, int alpha = 255) - : r(red), g(green), b(blue), a(alpha) { } + bool operator == (Color const &other) const + { + return other.r == r && other.g == g && other.b == b && other.a == a; + } - Color(): r(0), g(0), b(0), a(0) { } + bool operator != (Color const &other) const { return !operator == (other); } - bool operator == (Color const &other) const { - return other.r == r && other.g == g && other.b == b; } - - bool operator != (Color const &other) const { - return !operator == (other); } - - void print(Output &output) const + void print(Output &out) const { using Genode::print; - print(output, Char('#')); - print(output, Hex((unsigned char)r, Hex::OMIT_PREFIX, Hex::PAD)); - print(output, Hex((unsigned char)g, Hex::OMIT_PREFIX, Hex::PAD)); - print(output, Hex((unsigned char)b, Hex::OMIT_PREFIX, Hex::PAD)); + print(out, Char('#')); + print(out, Hex(r, Hex::OMIT_PREFIX, Hex::PAD)); + print(out, Hex(g, Hex::OMIT_PREFIX, Hex::PAD)); + print(out, Hex(b, Hex::OMIT_PREFIX, Hex::PAD)); if (a != 255) - print(output, Hex((unsigned char)a, Hex::OMIT_PREFIX, Hex::PAD)); + print(out, Hex(a, Hex::OMIT_PREFIX, Hex::PAD)); } }; @@ -64,27 +103,29 @@ struct Genode::Color * \return number of consumed characters, or 0 if the string contains * no valid color */ -inline Genode::size_t Genode::ascii_to(const char *s, Genode::Color &result) +inline Genode::size_t Genode::ascii_to(const char *s, Color &result) { - /* validate string */ - Genode::size_t const len = strlen(s); + size_t const len = strlen(s); if (len < 7 || *s != '#') return 0; - enum { HEX = true }; + bool const HEX = true; + + auto is_digit = [&] (unsigned i) { return Genode::is_digit(s[i], HEX); }; + auto digit = [&] (unsigned i) { return Genode::digit(s[i], HEX); }; for (unsigned i = 0; i < 6; i++) - if (!is_digit(s[i + 1], HEX)) return 0; + if (!is_digit(i + 1)) return 0; - int const red = 16*digit(s[1], HEX) + digit(s[2], HEX), - green = 16*digit(s[3], HEX) + digit(s[4], HEX), - blue = 16*digit(s[5], HEX) + digit(s[6], HEX); + uint8_t const r = uint8_t(16*digit(1) + digit(2)), + g = uint8_t(16*digit(3) + digit(4)), + b = uint8_t(16*digit(5) + digit(6)); - bool const has_alpha = (len >= 9) && is_digit(s[7], HEX) && is_digit(s[8], HEX); + bool const has_alpha = (len >= 9) && is_digit(7) && is_digit(8); - int const alpha = has_alpha ? 16*digit(s[7], HEX) + digit(s[8], HEX) : 255; + uint8_t const a = has_alpha ? uint8_t(16*digit(7) + digit(8)) : 255; - result = Color(red, green, blue, alpha); + result = Color { r, g, b, a }; return has_alpha ? 9 : 7; } diff --git a/repos/os/src/app/status_bar/main.cc b/repos/os/src/app/status_bar/main.cc index 632742c2fe..4cf33d1d95 100644 --- a/repos/os/src/app/status_bar/main.cc +++ b/repos/os/src/app/status_bar/main.cc @@ -77,7 +77,7 @@ struct Status_bar::Buffer if (i || j) Text_painter::paint(surface, Text_painter::Position(pos.x() + i, pos.y() + j), - _font, Color(0, 0, 0), s); + _font, Color::black(), s); } template @@ -85,10 +85,10 @@ struct Status_bar::Buffer Domain_name const &domain_name, Label const &label, Color color) { - Color const label_text_color((color.r + 255)/2, - (color.g + 255)/2, - (color.b + 255)/2); - Color const domain_text_color(255, 255, 255); + Color const label_text_color = Color::clamped_rgb((color.r + 255)/2, + (color.g + 255)/2, + (color.b + 255)/2); + Color const domain_text_color = Color::rgb(255, 255, 255); pos = pos + Point(1, 1); @@ -128,7 +128,7 @@ void Status_bar::Buffer::draw(Domain_name const &domain_name, Rect const view_rect(Point(0, 0), area); - int r = color.r, g = color.g, b = color.b; + unsigned r = color.r, g = color.g, b = color.b; /* dim session color a bit to improve the contrast of the label */ r = (r + 100)/2, g = (g + 100)/2, b = (b + 100)/2; @@ -136,7 +136,7 @@ void Status_bar::Buffer::draw(Domain_name const &domain_name, /* highlight first line with slightly brighter color */ Box_painter::paint(surface, Rect(Point(0, 0), Area(view_rect.w(), 1)), - Color(r + (r / 2), g + (g / 2), b + (b / 2))); + Color::clamped_rgb(r + (r / 2), g + (g / 2), b + (b / 2))); /* draw slightly shaded background */ for (unsigned i = 1; i < area.h() - 1; i++) { @@ -146,13 +146,13 @@ void Status_bar::Buffer::draw(Domain_name const &domain_name, Box_painter::paint(surface, Rect(Point(0, i), Area(view_rect.w(), 1)), - Color(r, g, b)); + Color::clamped_rgb(r, g, b)); } /* draw last line darker */ Box_painter::paint(surface, Rect(Point(0, view_rect.h() - 1), Area(view_rect.w(), 1)), - Color(r / 4, g / 4, b / 4)); + Color::clamped_rgb(r / 4, g / 4, b / 4)); _draw_label(surface, view_rect.center(_label_size(domain_name, label)), domain_name, label, color); @@ -220,7 +220,7 @@ void Status_bar::Main::_handle_focus() /* reset status-bar properties */ _label = Label(); _domain_name = Domain_name(); - _color = Color(0, 0, 0); + _color = Color::black(); /* read new focus information from nitpicker's focus report */ try { @@ -228,7 +228,7 @@ void Status_bar::Main::_handle_focus() _label = node.attribute_value("label", Label()); _domain_name = node.attribute_value("domain", Domain_name()); - _color = node.attribute_value("color", Color(0, 0, 0)); + _color = node.attribute_value("color", Color::black()); } catch (...) { warning("could not parse focus report"); } diff --git a/repos/os/src/server/nitpicker/background.h b/repos/os/src/server/nitpicker/background.h index 8cc0848960..1c7e5c317b 100644 --- a/repos/os/src/server/nitpicker/background.h +++ b/repos/os/src/server/nitpicker/background.h @@ -24,7 +24,7 @@ namespace Nitpicker { struct Background; } struct Nitpicker::Background : private Texture_base, View { - static Color default_color() { return Color(25, 37, 50); } + static constexpr Color default_color() { return Color::rgb(25, 37, 50); } Color color = default_color(); diff --git a/repos/os/src/server/nitpicker/draw_label.h b/repos/os/src/server/nitpicker/draw_label.h index 60ad92f595..b66c1005b4 100644 --- a/repos/os/src/server/nitpicker/draw_label.h +++ b/repos/os/src/server/nitpicker/draw_label.h @@ -34,7 +34,7 @@ namespace Nitpicker { for (int j = -1; j <= 1; j++) for (int i = -1; i <= 1; i++) if (i || j) - canvas.draw_text(pos + Point(i, j), font, black(), s); + canvas.draw_text(pos + Point(i, j), font, Color::black(), s); } diff --git a/repos/os/src/server/nitpicker/types.h b/repos/os/src/server/nitpicker/types.h index 41aea275a1..46edc25dc2 100644 --- a/repos/os/src/server/nitpicker/types.h +++ b/repos/os/src/server/nitpicker/types.h @@ -34,11 +34,7 @@ namespace Nitpicker { typedef Surface_base::Area Area; typedef Surface_base::Rect Rect; - /* - * Symbolic names for some important colors - */ - static inline Color black() { return Color(0, 0, 0); } - static inline Color white() { return Color(255, 255, 255); } + static constexpr Color white() { return Color::rgb(255, 255, 255); } class Gui_session; class View_stack; diff --git a/repos/os/src/server/nitpicker/view.cc b/repos/os/src/server/nitpicker/view.cc index 23cb222852..a2a069ce64 100644 --- a/repos/os/src/server/nitpicker/view.cc +++ b/repos/os/src/server/nitpicker/view.cc @@ -49,10 +49,10 @@ namespace Nitpicker { { /* draw frame around the view */ int d = frame_size; - draw_rect(canvas, r.x1() - d, r.y1() - d, r.w() + 2*d, r.h() + 2*d, black()); + draw_rect(canvas, r.x1() - d, r.y1() - d, r.w() + 2*d, r.h() + 2*d, Color::black()); while (--d > 1) draw_rect(canvas, r.x1() - d, r.y1() - d, r.w() + 2*d, r.h() + 2*d, color); - draw_rect(canvas, r.x1() - d, r.y1() - d, r.w() + 2*d, r.h() + 2*d, black()); + draw_rect(canvas, r.x1() - d, r.y1() - d, r.w() + 2*d, r.h() + 2*d, Color::black()); } @@ -122,16 +122,16 @@ void Nitpicker::View::draw(Canvas_base &canvas, Font const &font, Focus const &f /* draw view content */ Color const owner_color = _owner.color(); - Color const mix_color = Color(owner_color.r >> 1, - owner_color.g >> 1, - owner_color.b >> 1); + Color const mix_color = Color::rgb(owner_color.r >> 1, + owner_color.g >> 1, + owner_color.b >> 1); _texture.with_texture([&] (Texture_base const &texture) { canvas.draw_texture(_buffer_off + view_rect.p1(), texture, op, mix_color, allow_alpha); }); if (!_texture.valid()) - canvas.draw_box(view_rect, black()); + canvas.draw_box(view_rect, Color::black()); if (!_owner.label_visible()) return; diff --git a/repos/os/src/server/nitpicker/view_owner.h b/repos/os/src/server/nitpicker/view_owner.h index a35aa766b8..fa30d4a198 100644 --- a/repos/os/src/server/nitpicker/view_owner.h +++ b/repos/os/src/server/nitpicker/view_owner.h @@ -53,7 +53,7 @@ struct Nitpicker::View_owner : Interface virtual bool has_transient_focusable_domain() const { return false; } - virtual Color color() const { return black(); } + virtual Color color() const { return Color::black(); } virtual bool content_client() const { return true; }