mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-10 10:09:14 +00:00
LibWeb/CSS: Start parsing the color()
function
This is really bare bone as we only support the `xyz-d50` color space for the moment. It makes us pass the following WPT tests: - css/css-color/predefined-016.html - css/css-color/xyz-d50-001.html - css/css-color/xyz-d50-002.html
This commit is contained in:
parent
a6794627b0
commit
48bbebc636
Notes:
github-actions[bot]
2024-10-28 22:33:33 +00:00
Author: https://github.com/LucasChollet
Commit: 48bbebc636
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2003
7 changed files with 166 additions and 0 deletions
|
@ -7,6 +7,7 @@ source_set("StyleValues") {
|
||||||
"BackgroundSizeStyleValue.cpp",
|
"BackgroundSizeStyleValue.cpp",
|
||||||
"BasicShapeStyleValue.cpp",
|
"BasicShapeStyleValue.cpp",
|
||||||
"BorderRadiusStyleValue.cpp",
|
"BorderRadiusStyleValue.cpp",
|
||||||
|
"CSSColor.cpp",
|
||||||
"CSSColorValue.cpp",
|
"CSSColorValue.cpp",
|
||||||
"CSSHSL.cpp",
|
"CSSHSL.cpp",
|
||||||
"CSSHWB.cpp",
|
"CSSHWB.cpp",
|
||||||
|
|
|
@ -115,6 +115,7 @@ set(SOURCES
|
||||||
CSS/StyleValues/ContentStyleValue.cpp
|
CSS/StyleValues/ContentStyleValue.cpp
|
||||||
CSS/StyleValues/CounterDefinitionsStyleValue.cpp
|
CSS/StyleValues/CounterDefinitionsStyleValue.cpp
|
||||||
CSS/StyleValues/CounterStyleValue.cpp
|
CSS/StyleValues/CounterStyleValue.cpp
|
||||||
|
CSS/StyleValues/CSSColor.cpp
|
||||||
CSS/StyleValues/CSSColorValue.cpp
|
CSS/StyleValues/CSSColorValue.cpp
|
||||||
CSS/StyleValues/CSSHSL.cpp
|
CSS/StyleValues/CSSHSL.cpp
|
||||||
CSS/StyleValues/CSSHWB.cpp
|
CSS/StyleValues/CSSHWB.cpp
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
#include <LibWeb/CSS/StyleValues/BackgroundSizeStyleValue.h>
|
#include <LibWeb/CSS/StyleValues/BackgroundSizeStyleValue.h>
|
||||||
#include <LibWeb/CSS/StyleValues/BasicShapeStyleValue.h>
|
#include <LibWeb/CSS/StyleValues/BasicShapeStyleValue.h>
|
||||||
#include <LibWeb/CSS/StyleValues/BorderRadiusStyleValue.h>
|
#include <LibWeb/CSS/StyleValues/BorderRadiusStyleValue.h>
|
||||||
|
#include <LibWeb/CSS/StyleValues/CSSColor.h>
|
||||||
#include <LibWeb/CSS/StyleValues/CSSColorValue.h>
|
#include <LibWeb/CSS/StyleValues/CSSColorValue.h>
|
||||||
#include <LibWeb/CSS/StyleValues/CSSHSL.h>
|
#include <LibWeb/CSS/StyleValues/CSSHSL.h>
|
||||||
#include <LibWeb/CSS/StyleValues/CSSHWB.h>
|
#include <LibWeb/CSS/StyleValues/CSSHWB.h>
|
||||||
|
@ -3387,6 +3388,66 @@ RefPtr<CSSStyleValue> Parser::parse_oklch_color_value(TokenStream<ComponentValue
|
||||||
return CSSOKLCH::create(l.release_nonnull(), c.release_nonnull(), h.release_nonnull(), alpha.release_nonnull());
|
return CSSOKLCH::create(l.release_nonnull(), c.release_nonnull(), h.release_nonnull(), alpha.release_nonnull());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/css-color-4/#funcdef-color
|
||||||
|
RefPtr<CSSStyleValue> Parser::parse_color_function(TokenStream<ComponentValue>& outer_tokens)
|
||||||
|
{
|
||||||
|
// color() = color( <colorspace-params> [ / [ <alpha-value> | none ] ]? )
|
||||||
|
// <colorspace-params> = [ <predefined-rgb-params> | <xyz-params>]
|
||||||
|
// <predefined-rgb-params> = <predefined-rgb> [ <number> | <percentage> | none ]{3}
|
||||||
|
// <predefined-rgb> = srgb | srgb-linear | display-p3 | a98-rgb | prophoto-rgb | rec2020
|
||||||
|
// <xyz-params> = <xyz-space> [ <number> | <percentage> | none ]{3}
|
||||||
|
// <xyz-space> = xyz | xyz-d50 | xyz-d65
|
||||||
|
|
||||||
|
auto transaction = outer_tokens.begin_transaction();
|
||||||
|
outer_tokens.discard_whitespace();
|
||||||
|
|
||||||
|
auto const& function_token = outer_tokens.consume_a_token();
|
||||||
|
if (!function_token.is_function("color"sv))
|
||||||
|
return {};
|
||||||
|
|
||||||
|
auto inner_tokens = TokenStream { function_token.function().value };
|
||||||
|
inner_tokens.discard_whitespace();
|
||||||
|
|
||||||
|
auto maybe_color_space = inner_tokens.consume_a_token();
|
||||||
|
inner_tokens.discard_whitespace();
|
||||||
|
if (!any_of(CSSColor::s_supported_color_space, [&](auto supported) { return maybe_color_space.is_ident(supported); }))
|
||||||
|
return {};
|
||||||
|
|
||||||
|
auto const& color_space = maybe_color_space.token().ident();
|
||||||
|
|
||||||
|
auto c1 = parse_number_percentage_value(inner_tokens);
|
||||||
|
if (!c1)
|
||||||
|
return {};
|
||||||
|
inner_tokens.discard_whitespace();
|
||||||
|
|
||||||
|
auto c2 = parse_number_percentage_value(inner_tokens);
|
||||||
|
if (!c2)
|
||||||
|
return {};
|
||||||
|
inner_tokens.discard_whitespace();
|
||||||
|
|
||||||
|
auto c3 = parse_number_percentage_value(inner_tokens);
|
||||||
|
if (!c3)
|
||||||
|
return {};
|
||||||
|
inner_tokens.discard_whitespace();
|
||||||
|
|
||||||
|
RefPtr<CSSStyleValue> alpha;
|
||||||
|
if (inner_tokens.has_next_token()) {
|
||||||
|
alpha = parse_solidus_and_alpha_value(inner_tokens);
|
||||||
|
if (!alpha || inner_tokens.has_next_token())
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!alpha)
|
||||||
|
alpha = NumberStyleValue::create(1);
|
||||||
|
|
||||||
|
transaction.commit();
|
||||||
|
return CSSColor::create(color_space.to_ascii_lowercase(),
|
||||||
|
c1.release_nonnull(),
|
||||||
|
c2.release_nonnull(),
|
||||||
|
c3.release_nonnull(),
|
||||||
|
alpha.release_nonnull());
|
||||||
|
}
|
||||||
|
|
||||||
// https://www.w3.org/TR/css-color-4/#color-syntax
|
// https://www.w3.org/TR/css-color-4/#color-syntax
|
||||||
RefPtr<CSSStyleValue> Parser::parse_color_value(TokenStream<ComponentValue>& tokens)
|
RefPtr<CSSStyleValue> Parser::parse_color_value(TokenStream<ComponentValue>& tokens)
|
||||||
{
|
{
|
||||||
|
@ -3401,6 +3462,9 @@ RefPtr<CSSStyleValue> Parser::parse_color_value(TokenStream<ComponentValue>& tok
|
||||||
}
|
}
|
||||||
|
|
||||||
// Functions
|
// Functions
|
||||||
|
if (auto color = parse_color_function(tokens))
|
||||||
|
return color;
|
||||||
|
|
||||||
if (auto rgb = parse_rgb_color_value(tokens))
|
if (auto rgb = parse_rgb_color_value(tokens))
|
||||||
return rgb;
|
return rgb;
|
||||||
if (auto hsl = parse_hsl_color_value(tokens))
|
if (auto hsl = parse_hsl_color_value(tokens))
|
||||||
|
|
|
@ -254,6 +254,7 @@ private:
|
||||||
RefPtr<CSSStyleValue> parse_lab_color_value(TokenStream<ComponentValue>&);
|
RefPtr<CSSStyleValue> parse_lab_color_value(TokenStream<ComponentValue>&);
|
||||||
RefPtr<CSSStyleValue> parse_oklab_color_value(TokenStream<ComponentValue>&);
|
RefPtr<CSSStyleValue> parse_oklab_color_value(TokenStream<ComponentValue>&);
|
||||||
RefPtr<CSSStyleValue> parse_oklch_color_value(TokenStream<ComponentValue>&);
|
RefPtr<CSSStyleValue> parse_oklch_color_value(TokenStream<ComponentValue>&);
|
||||||
|
RefPtr<CSSStyleValue> parse_color_function(TokenStream<ComponentValue>&);
|
||||||
RefPtr<CSSStyleValue> parse_color_value(TokenStream<ComponentValue>&);
|
RefPtr<CSSStyleValue> parse_color_value(TokenStream<ComponentValue>&);
|
||||||
RefPtr<CSSStyleValue> parse_counter_value(TokenStream<ComponentValue>&);
|
RefPtr<CSSStyleValue> parse_counter_value(TokenStream<ComponentValue>&);
|
||||||
enum class AllowReversed {
|
enum class AllowReversed {
|
||||||
|
|
58
Userland/Libraries/LibWeb/CSS/StyleValues/CSSColor.cpp
Normal file
58
Userland/Libraries/LibWeb/CSS/StyleValues/CSSColor.cpp
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024, Lucas Chollet <lucas.chollet@serenityos.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CSSColor.h"
|
||||||
|
#include <AK/TypeCasts.h>
|
||||||
|
#include <LibWeb/CSS/Serialize.h>
|
||||||
|
#include <LibWeb/CSS/StyleValues/NumberStyleValue.h>
|
||||||
|
|
||||||
|
namespace Web::CSS {
|
||||||
|
|
||||||
|
ValueComparingNonnullRefPtr<CSSColor> CSSColor::create(StringView color_space, ValueComparingNonnullRefPtr<CSSStyleValue> c1, ValueComparingNonnullRefPtr<CSSStyleValue> c2, ValueComparingNonnullRefPtr<CSSStyleValue> c3, ValueComparingRefPtr<CSSStyleValue> alpha)
|
||||||
|
{
|
||||||
|
VERIFY(any_of(s_supported_color_space, [=](auto supported) { return color_space == supported; }));
|
||||||
|
|
||||||
|
if (!alpha)
|
||||||
|
alpha = NumberStyleValue::create(1);
|
||||||
|
|
||||||
|
if (color_space == "xyz-d50")
|
||||||
|
return adopt_ref(*new (nothrow) CSSColor(ColorType::XYZD50, move(c1), move(c2), move(c3), alpha.release_nonnull()));
|
||||||
|
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSSColor::equals(CSSStyleValue 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_lab_like = verify_cast<CSSColor>(other_color);
|
||||||
|
return m_properties == other_lab_like.m_properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/css-color-4/#serializing-color-function-values
|
||||||
|
String CSSColor::to_string() const
|
||||||
|
{
|
||||||
|
// FIXME: Do this properly, taking unresolved calculated values into account.
|
||||||
|
return serialize_a_srgb_value(to_color({}));
|
||||||
|
}
|
||||||
|
|
||||||
|
Color CSSColor::to_color(Optional<Layout::NodeWithStyle const&>) const
|
||||||
|
{
|
||||||
|
auto const c1 = resolve_with_reference_value(m_properties.channels[0], 100).value_or(0);
|
||||||
|
auto const c2 = resolve_with_reference_value(m_properties.channels[1], 100).value_or(0);
|
||||||
|
auto const c3 = resolve_with_reference_value(m_properties.channels[2], 100).value_or(0);
|
||||||
|
auto const alpha_val = resolve_alpha(m_properties.alpha).value_or(1);
|
||||||
|
|
||||||
|
if (color_type() == ColorType::XYZD50)
|
||||||
|
return Color::from_xyz50(c1, c2, c3, alpha_val);
|
||||||
|
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Web::CSS
|
40
Userland/Libraries/LibWeb/CSS/StyleValues/CSSColor.h
Normal file
40
Userland/Libraries/LibWeb/CSS/StyleValues/CSSColor.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024, Lucas Chollet <lucas.chollet@serenityos.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <LibWeb/CSS/StyleValues/CSSColorValue.h>
|
||||||
|
|
||||||
|
namespace Web::CSS {
|
||||||
|
|
||||||
|
// https://drafts.css-houdini.org/css-typed-om-1/#csscolor
|
||||||
|
class CSSColor final : public CSSColorValue {
|
||||||
|
public:
|
||||||
|
virtual ~CSSColor() override = default;
|
||||||
|
|
||||||
|
static ValueComparingNonnullRefPtr<CSSColor> create(StringView color_space, ValueComparingNonnullRefPtr<CSSStyleValue> c1, ValueComparingNonnullRefPtr<CSSStyleValue> c2, ValueComparingNonnullRefPtr<CSSStyleValue> c3, ValueComparingRefPtr<CSSStyleValue> alpha = {});
|
||||||
|
|
||||||
|
virtual bool equals(CSSStyleValue const&) const override;
|
||||||
|
virtual Color to_color(Optional<Layout::NodeWithStyle const&>) const override;
|
||||||
|
virtual String to_string() const override;
|
||||||
|
|
||||||
|
static constexpr Array s_supported_color_space = { "xyz-d50"sv };
|
||||||
|
|
||||||
|
private:
|
||||||
|
CSSColor(ColorType color_type, ValueComparingNonnullRefPtr<CSSStyleValue> c1, ValueComparingNonnullRefPtr<CSSStyleValue> c2, ValueComparingNonnullRefPtr<CSSStyleValue> c3, ValueComparingNonnullRefPtr<CSSStyleValue> alpha)
|
||||||
|
: CSSColorValue(color_type)
|
||||||
|
, m_properties { .channels = { move(c1), move(c2), move(c3) }, .alpha = move(alpha) }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Properties {
|
||||||
|
Array<ValueComparingNonnullRefPtr<CSSStyleValue>, 3> channels;
|
||||||
|
ValueComparingNonnullRefPtr<CSSStyleValue> alpha;
|
||||||
|
bool operator==(Properties const&) const = default;
|
||||||
|
} m_properties;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // Web::CSS
|
|
@ -29,6 +29,7 @@ public:
|
||||||
Lab,
|
Lab,
|
||||||
OKLab,
|
OKLab,
|
||||||
OKLCH,
|
OKLCH,
|
||||||
|
XYZD50,
|
||||||
};
|
};
|
||||||
ColorType color_type() const { return m_color_type; }
|
ColorType color_type() const { return m_color_type; }
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue