LibWeb/CSS: Implement the color-scheme CSS property

This commit is contained in:
Gingeh 2025-01-02 12:59:09 +11:00 committed by Sam Atkins
commit ce5cd012b9
Notes: github-actions[bot] 2025-01-08 11:19:41 +00:00
36 changed files with 618 additions and 370 deletions

View file

@ -7,6 +7,7 @@
*/
#include <AK/CircularQueue.h>
#include <LibWeb/CSS/StyleValues/CSSKeywordValue.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/Layout/Node.h>
@ -579,7 +580,7 @@ Optional<BordersData> borders_data_for_outline(Layout::Node const& layout_node,
if (outline_style == CSS::OutlineStyle::Auto) {
// `auto` lets us do whatever we want for the outline. 2px of the link colour seems reasonable.
line_style = CSS::LineStyle::Dotted;
outline_color = layout_node.document().normal_link_color();
outline_color = CSS::CSSKeywordValue::create(CSS::Keyword::Linktext)->to_color(*static_cast<Layout::NodeWithStyle const*>(&layout_node));
outline_width = 2;
} else {
line_style = CSS::keyword_to_line_style(CSS::to_keyword(outline_style)).value_or(CSS::LineStyle::None);

View file

@ -72,10 +72,8 @@ void CheckBoxPaintable::paint(PaintContext& context, PaintPhase phase) const
auto checkbox_rect = context.enclosing_device_rect(absolute_rect()).to_type<int>();
auto checkbox_radius = checkbox_rect.width() / 5;
auto& palette = context.palette();
auto shade = [&](Color color, float amount) {
return InputColors::get_shade(color, amount, palette.is_dark());
return InputColors::get_shade(color, amount, computed_values().color_scheme());
};
auto modify_color = [&](Color color) {
@ -84,7 +82,7 @@ void CheckBoxPaintable::paint(PaintContext& context, PaintPhase phase) const
return color;
};
auto input_colors = compute_input_colors(palette, computed_values().accent_color());
auto input_colors = compute_input_colors(computed_values().color_scheme(), computed_values().accent_color());
auto increase_contrast = [&](Color color, Color background) {
auto constexpr min_contrast = 2;

View file

@ -9,6 +9,7 @@
#include <AK/Optional.h>
#include <LibGfx/Color.h>
#include <LibGfx/Palette.h>
#include <LibWeb/CSS/SystemColor.h>
namespace Web::Painting {
@ -25,24 +26,24 @@ struct InputColors {
Color background_color(bool enabled) { return enabled ? base : light_gray; }
Color border_color(bool enabled) { return enabled ? gray : mid_gray; }
static Color get_shade(Color color, float amount, bool is_dark_theme)
static Color get_shade(Color color, float amount, CSS::PreferredColorScheme color_scheme)
{
return color.mixed_with(is_dark_theme ? Color::Black : Color::White, amount);
auto base_color = CSS::SystemColor::canvas(color_scheme);
return color.mixed_with(base_color, amount);
}
};
static InputColors compute_input_colors(Palette const& palette, Optional<Color> accent_color)
static InputColors compute_input_colors(CSS::PreferredColorScheme color_scheme, Optional<Color> accent_color)
{
// These shades have been picked to work well for all themes and have enough variation to paint
// all input states (disabled, enabled, checked, etc).
bool dark_theme = palette.is_dark();
auto base_text_color = palette.color(ColorRole::BaseText);
auto accent = accent_color.value_or(palette.color(ColorRole::Accent));
auto base = InputColors::get_shade(base_text_color.inverted(), 0.8f, dark_theme);
auto dark_gray = InputColors::get_shade(base_text_color, 0.3f, dark_theme);
auto gray = InputColors::get_shade(dark_gray, 0.4f, dark_theme);
auto mid_gray = InputColors::get_shade(gray, 0.3f, dark_theme);
auto light_gray = InputColors::get_shade(mid_gray, 0.3f, dark_theme);
auto base_text_color = CSS::SystemColor::canvas_text(color_scheme);
auto accent = accent_color.value_or(CSS::SystemColor::accent_color(color_scheme));
auto base = InputColors::get_shade(base_text_color.inverted(), 0.8f, color_scheme);
auto dark_gray = InputColors::get_shade(base_text_color, 0.3f, color_scheme);
auto gray = InputColors::get_shade(dark_gray, 0.4f, color_scheme);
auto mid_gray = InputColors::get_shade(gray, 0.3f, color_scheme);
auto light_gray = InputColors::get_shade(mid_gray, 0.3f, color_scheme);
return InputColors {
.accent = accent,
.base = base,

View file

@ -692,10 +692,10 @@ void paint_text_fragment(PaintContext& context, TextPaintable const& paintable,
auto selection_rect = context.enclosing_device_rect(fragment.selection_rect()).to_type<int>();
if (!selection_rect.is_empty()) {
painter.fill_rect(selection_rect, CSS::SystemColor::highlight());
painter.fill_rect(selection_rect, CSS::SystemColor::highlight(paintable.computed_values().color_scheme()));
DisplayListRecorderStateSaver saver(painter);
painter.add_clip_rect(selection_rect);
painter.draw_text_run(baseline_start, *glyph_run, CSS::SystemColor::highlight_text(), fragment_absolute_device_rect.to_type<int>(), scale, fragment.orientation());
painter.draw_text_run(baseline_start, *glyph_run, CSS::SystemColor::highlight_text(paintable.computed_values().color_scheme()), fragment_absolute_device_rect.to_type<int>(), scale, fragment.orientation());
}
paint_text_decoration(context, paintable, fragment);

View file

@ -49,9 +49,8 @@ void RadioButtonPaintable::paint(PaintContext& context, PaintPhase phase) const
auto const& radio_button = static_cast<HTML::HTMLInputElement const&>(layout_box().dom_node());
auto& palette = context.palette();
bool enabled = layout_box().dom_node().enabled();
auto input_colors = compute_input_colors(palette, computed_values().accent_color());
auto input_colors = compute_input_colors(computed_values().color_scheme(), computed_values().accent_color());
auto background_color = input_colors.background_color(enabled);
auto accent = input_colors.accent;
@ -71,7 +70,7 @@ void RadioButtonPaintable::paint(PaintContext& context, PaintPhase phase) const
return input_colors.mid_gray;
auto color = radio_color();
if (being_pressed())
color = InputColors::get_shade(color, 0.3f, palette.is_dark());
color = InputColors::get_shade(color, 0.3f, computed_values().color_scheme());
return color;
}();