LibWeb: Route hsl()/hsla() through unified ColorFunctionStyleValue
This commit is contained in:
parent
9ea880dcf0
commit
ebe12a8766
6 changed files with 7 additions and 181 deletions
|
|
@ -265,7 +265,6 @@ set(SOURCES
|
|||
CSS/StyleValues/GridTemplateAreaStyleValue.cpp
|
||||
CSS/StyleValues/GridTrackPlacementStyleValue.cpp
|
||||
CSS/StyleValues/GridTrackSizeListStyleValue.cpp
|
||||
CSS/StyleValues/HSLColorStyleValue.cpp
|
||||
CSS/StyleValues/HWBColorStyleValue.cpp
|
||||
CSS/StyleValues/ImageStyleValue.cpp
|
||||
CSS/StyleValues/IntegerStyleValue.cpp
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
#include <LibWeb/CSS/ColorInterpolation.h>
|
||||
#include <LibWeb/CSS/Interpolation.h>
|
||||
#include <LibWeb/CSS/StyleValues/ColorFunctionStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/HSLColorStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/HWBColorStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/KeywordStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/LCHLikeColorStyleValue.h>
|
||||
|
|
@ -125,8 +124,8 @@ static MissingComponents extract_missing_components(StyleValue const& style_valu
|
|||
return {};
|
||||
switch (*color_type) {
|
||||
case ColorStyleValue::ColorType::HSL: {
|
||||
auto const& hsl = as<HSLColorStyleValue>(color);
|
||||
return { is_component_none(hsl.h()), is_component_none(hsl.s()), is_component_none(hsl.l()), is_component_none(hsl.alpha()) };
|
||||
auto const& hsl = as<ColorFunctionStyleValue>(color);
|
||||
return { is_component_none(hsl.channel(0)), is_component_none(hsl.channel(1)), is_component_none(hsl.channel(2)), is_component_none(hsl.alpha()) };
|
||||
}
|
||||
case ColorStyleValue::ColorType::HWB: {
|
||||
auto const& hwb = as<HWBColorStyleValue>(color);
|
||||
|
|
@ -399,10 +398,10 @@ static Optional<Gfx::ColorComponents> style_value_to_color_components(StyleValue
|
|||
|
||||
switch (*color_type) {
|
||||
case ColorStyleValue::ColorType::HSL: {
|
||||
auto const& hsl = as<HSLColorStyleValue>(color);
|
||||
auto h = ColorStyleValue::resolve_hue(hsl.h(), context);
|
||||
auto s = ColorStyleValue::resolve_with_reference_value(hsl.s(), 100.0f, context);
|
||||
auto l = ColorStyleValue::resolve_with_reference_value(hsl.l(), 100.0f, context);
|
||||
auto const& hsl = as<ColorFunctionStyleValue>(color);
|
||||
auto h = ColorStyleValue::resolve_hue(hsl.channel(0), context);
|
||||
auto s = ColorStyleValue::resolve_with_reference_value(hsl.channel(1), 100.0f, context);
|
||||
auto l = ColorStyleValue::resolve_with_reference_value(hsl.channel(2), 100.0f, context);
|
||||
auto a = resolve_alpha(hsl.alpha());
|
||||
if (!h.has_value() || !s.has_value() || !l.has_value() || !a.has_value())
|
||||
return {};
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@
|
|||
#include <LibWeb/CSS/StyleValues/GridTrackPlacementStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/GridTrackSizeListStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/GuaranteedInvalidStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/HSLColorStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/HWBColorStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/ImageStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/IntegerStyleValue.h>
|
||||
|
|
@ -1683,7 +1682,7 @@ RefPtr<StyleValue const> Parser::parse_hsl_color_value(TokenStream<ComponentValu
|
|||
alpha = NumberStyleValue::create(1);
|
||||
|
||||
transaction.commit();
|
||||
return HSLColorStyleValue::create(h.release_nonnull(), s.release_nonnull(), l.release_nonnull(), alpha.release_nonnull(), legacy_syntax ? ColorSyntax::Legacy : ColorSyntax::Modern);
|
||||
return ColorFunctionStyleValue::create(ColorStyleValue::ColorType::HSL, h.release_nonnull(), s.release_nonnull(), l.release_nonnull(), alpha.release_nonnull(), legacy_syntax ? ColorSyntax::Legacy : ColorSyntax::Modern);
|
||||
}
|
||||
|
||||
// https://www.w3.org/TR/css-color-4/#funcdef-hwb
|
||||
|
|
|
|||
|
|
@ -1,107 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2024-2026, Sam Atkins <sam@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include "HSLColorStyleValue.h"
|
||||
#include <AK/TypeCasts.h>
|
||||
#include <LibWeb/CSS/Serialize.h>
|
||||
#include <LibWeb/CSS/StyleValues/CalculatedStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/ColorFunctionStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/NumberStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/PercentageStyleValue.h>
|
||||
|
||||
namespace Web::CSS {
|
||||
|
||||
Optional<Color> HSLColorStyleValue::to_color(ColorResolutionContext color_resolution_context) const
|
||||
{
|
||||
auto h_val = resolve_hue(m_properties.h, color_resolution_context.calculation_resolution_context);
|
||||
auto s_val = resolve_with_reference_value(m_properties.s, 100.0, color_resolution_context.calculation_resolution_context);
|
||||
auto l_val = resolve_with_reference_value(m_properties.l, 100.0, color_resolution_context.calculation_resolution_context);
|
||||
auto alpha_val = resolve_alpha(m_properties.alpha, color_resolution_context.calculation_resolution_context);
|
||||
|
||||
if (!h_val.has_value() || !s_val.has_value() || !l_val.has_value() || !alpha_val.has_value())
|
||||
return {};
|
||||
|
||||
return Color::from_hsla(h_val.value(), s_val.value() / 100.0f, l_val.value() / 100.0f, alpha_val.value());
|
||||
}
|
||||
|
||||
ValueComparingNonnullRefPtr<StyleValue const> HSLColorStyleValue::absolutized(ComputationContext const& context) const
|
||||
{
|
||||
auto absolutized_h = m_properties.h->absolutized(context);
|
||||
auto absolutized_s = m_properties.s->absolutized(context);
|
||||
auto absolutized_l = m_properties.l->absolutized(context);
|
||||
auto absolutized_alpha = m_properties.alpha->absolutized(context);
|
||||
|
||||
// hsl() computes to rgb()
|
||||
// https://drafts.csswg.org/css-color-4/#resolving-sRGB-values
|
||||
auto resolved_h = resolve_hue(absolutized_h, {});
|
||||
auto resolved_s = resolve_with_reference_value(absolutized_s, 100.0, {});
|
||||
auto resolved_l = resolve_with_reference_value(absolutized_l, 100.0, {});
|
||||
auto resolved_alpha = resolve_alpha(absolutized_alpha, {});
|
||||
|
||||
// These should all be computable at this point.
|
||||
if (!resolved_h.has_value() || !resolved_s.has_value() || !resolved_l.has_value() || !resolved_alpha.has_value())
|
||||
VERIFY_NOT_REACHED();
|
||||
|
||||
// https://drafts.csswg.org/css-color-4/#hsl-to-rgb
|
||||
auto hue = fmod(resolved_h.value(), 360.0);
|
||||
if (hue < 0.0)
|
||||
hue += 360.0;
|
||||
auto saturation = clamp(resolved_s.value() / 100.0, 0.0, 1.0);
|
||||
auto lightness = clamp(resolved_l.value() / 100.0, 0.0, 1.0);
|
||||
|
||||
auto to_rgb = [](auto h, auto s, auto l, auto offset) {
|
||||
auto k = fmod(offset + h / 30.0, 12.0);
|
||||
auto a = s * min(l, 1.0 - l);
|
||||
return l - a * max(-1.0, min(min(k - 3.0, 9.0 - k), 1.0));
|
||||
};
|
||||
|
||||
auto r = to_rgb(hue, saturation, lightness, 0.0);
|
||||
auto g = to_rgb(hue, saturation, lightness, 8.0);
|
||||
auto b = to_rgb(hue, saturation, lightness, 4.0);
|
||||
|
||||
return ColorFunctionStyleValue::create(
|
||||
ColorType::RGB,
|
||||
NumberStyleValue::create(clamp(r * 255.0, 0, 255)),
|
||||
NumberStyleValue::create(clamp(g * 255.0, 0, 255)),
|
||||
NumberStyleValue::create(clamp(b * 255.0, 0, 255)),
|
||||
NumberStyleValue::create(clamp(resolved_alpha.value(), 0.0, 1.0)),
|
||||
ColorSyntax::Legacy);
|
||||
}
|
||||
|
||||
bool HSLColorStyleValue::equals(StyleValue const& other) const
|
||||
{
|
||||
if (type() != other.type())
|
||||
return false;
|
||||
auto const& other_color = other.as_color();
|
||||
if (color_type() != other_color.color_type())
|
||||
return false;
|
||||
auto const& other_hsl = as<HSLColorStyleValue>(other_color);
|
||||
return m_properties == other_hsl.m_properties;
|
||||
}
|
||||
|
||||
// https://www.w3.org/TR/css-color-4/#serializing-sRGB-values
|
||||
void HSLColorStyleValue::serialize(StringBuilder& builder, SerializationMode mode) const
|
||||
{
|
||||
if (auto color = to_color({}); color.has_value()) {
|
||||
builder.append(color->serialize_a_srgb_value());
|
||||
return;
|
||||
}
|
||||
|
||||
builder.append("hsl("sv);
|
||||
serialize_hue_component(builder, mode, m_properties.h);
|
||||
builder.append(" "sv);
|
||||
serialize_color_component(builder, mode, m_properties.s, 100, 0);
|
||||
builder.append(" "sv);
|
||||
serialize_color_component(builder, mode, m_properties.l, 100, 0);
|
||||
if ((!m_properties.alpha->is_number() || m_properties.alpha->as_number().number() < 1) && (!m_properties.alpha->is_percentage() || m_properties.alpha->as_percentage().percentage().as_fraction() < 1)) {
|
||||
builder.append(" / "sv);
|
||||
serialize_alpha_component(builder, mode, m_properties.alpha);
|
||||
}
|
||||
|
||||
builder.append(")"sv);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2024-2026, Sam Atkins <sam@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibWeb/CSS/StyleValues/ColorStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/ComputationContext.h>
|
||||
#include <LibWeb/CSS/StyleValues/NumberStyleValue.h>
|
||||
|
||||
namespace Web::CSS {
|
||||
|
||||
class HSLColorStyleValue final : public ColorStyleValue {
|
||||
public:
|
||||
static ValueComparingNonnullRefPtr<HSLColorStyleValue const> create(ValueComparingNonnullRefPtr<StyleValue const> h, ValueComparingNonnullRefPtr<StyleValue const> s, ValueComparingNonnullRefPtr<StyleValue const> l, ValueComparingRefPtr<StyleValue const> alpha, ColorSyntax color_syntax)
|
||||
{
|
||||
// alpha defaults to 1
|
||||
if (!alpha)
|
||||
return adopt_ref(*new (nothrow) HSLColorStyleValue(move(h), move(s), move(l), NumberStyleValue::create(1), color_syntax));
|
||||
|
||||
return adopt_ref(*new (nothrow) HSLColorStyleValue(move(h), move(s), move(l), alpha.release_nonnull(), color_syntax));
|
||||
}
|
||||
virtual ~HSLColorStyleValue() override = default;
|
||||
|
||||
StyleValue const& h() const { return *m_properties.h; }
|
||||
StyleValue const& s() const { return *m_properties.s; }
|
||||
StyleValue const& l() const { return *m_properties.l; }
|
||||
StyleValue const& alpha() const { return *m_properties.alpha; }
|
||||
|
||||
virtual Optional<Color> to_color(ColorResolutionContext color_resolution_context) const override;
|
||||
virtual ValueComparingNonnullRefPtr<StyleValue const> absolutized(ComputationContext const&) const override;
|
||||
|
||||
virtual void serialize(StringBuilder&, SerializationMode) const override;
|
||||
|
||||
virtual bool equals(StyleValue const& other) const override;
|
||||
|
||||
virtual bool is_computationally_independent() const override
|
||||
{
|
||||
return m_properties.h->is_computationally_independent()
|
||||
&& m_properties.s->is_computationally_independent()
|
||||
&& m_properties.l->is_computationally_independent()
|
||||
&& m_properties.alpha->is_computationally_independent();
|
||||
}
|
||||
|
||||
private:
|
||||
HSLColorStyleValue(ValueComparingNonnullRefPtr<StyleValue const> h, ValueComparingNonnullRefPtr<StyleValue const> s, ValueComparingNonnullRefPtr<StyleValue const> l, ValueComparingNonnullRefPtr<StyleValue const> alpha, ColorSyntax color_syntax)
|
||||
: ColorStyleValue(ColorType::HSL, color_syntax)
|
||||
, m_properties { .h = move(h), .s = move(s), .l = move(l), .alpha = move(alpha) }
|
||||
{
|
||||
}
|
||||
|
||||
struct Properties {
|
||||
ValueComparingNonnullRefPtr<StyleValue const> h;
|
||||
ValueComparingNonnullRefPtr<StyleValue const> s;
|
||||
ValueComparingNonnullRefPtr<StyleValue const> l;
|
||||
ValueComparingNonnullRefPtr<StyleValue const> alpha;
|
||||
bool operator==(Properties const&) const = default;
|
||||
} m_properties;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -343,7 +343,6 @@ class GridTrackPlacementStyleValue;
|
|||
class GridTrackSizeList;
|
||||
class GridTrackSizeListStyleValue;
|
||||
class GuaranteedInvalidStyleValue;
|
||||
class HSLColorStyleValue;
|
||||
class HWBColorStyleValue;
|
||||
class ImageStyleValue;
|
||||
class IntegerStyleValue;
|
||||
|
|
|
|||
Loading…
Reference in a new issue