LibWeb/CSS: Add support for the rec2020 color space in color()

This color space is often used as a reference in WPT tests, having
support for it makes us pass 15 new tests:
  - css/css-color/rec2020-001.html
  - css/css-color/rec2020-002.html
  - css/css-color/rec2020-003.html
  - css/css-color/rec2020-004.html
  - css/css-color/rec2020-005.html
  - css/css-color/predefined-011.html
  - css/css-color/predefined-012.html
This commit is contained in:
Lucas CHOLLET 2024-11-14 22:43:43 -05:00 committed by Andreas Kling
parent 2173219eac
commit 63873f3809
Notes: github-actions[bot] 2024-11-16 09:30:38 +00:00
14 changed files with 170 additions and 1 deletions

View file

@ -476,6 +476,33 @@ Color Color::from_pro_photo_rgb(float r, float g, float b, float alpha)
return from_xyz50(x, y, z, alpha);
}
// https://www.w3.org/TR/css-color-4/#predefined-rec2020
Color Color::from_rec2020(float r, float g, float b, float alpha)
{
auto to_linear = [](float c) -> float {
auto constexpr alpha = 1.09929682680944;
auto constexpr beta = 0.018053968510807;
u8 sign = c < 0 ? -1 : 1;
auto absolute = abs(c);
if (absolute < beta * 4.5)
return c / 4.5;
return sign * (pow((absolute + alpha - 1) / alpha, 1 / 0.45));
};
auto linear_r = to_linear(r);
auto linear_g = to_linear(g);
auto linear_b = to_linear(b);
float x = 0.63695805 * linear_r + 0.14461690 * linear_g + 0.16888098 * linear_b;
float y = 0.26270021 * linear_r + 0.67799807 * linear_g + 0.05930172 * linear_b;
float z = 0.00000000 * linear_r + 0.02807269 * linear_g + 1.06098506 * linear_b;
return from_xyz65(x, y, z, alpha);
}
Color Color::from_xyz50(float x, float y, float z, float alpha)
{
// See commit description for these values

View file

@ -187,6 +187,7 @@ public:
static Color from_lab(float L, float a, float b, float alpha = 1.0f);
static Color from_linear_srgb(float r, float g, float b, float alpha = 1.0f);
static Color from_pro_photo_rgb(float r, float g, float b, float alpha = 1.0f);
static Color from_rec2020(float r, float g, float b, float alpha = 1.0f);
static Color from_xyz50(float x, float y, float z, float alpha = 1.0f);
static Color from_xyz65(float x, float y, float z, float alpha = 1.0f);

View file

@ -25,6 +25,8 @@ CSSColorValue::ColorType color_type_from_string_view(StringView color_space)
return CSSColorValue::ColorType::sRGBLinear;
if (color_space == "prophoto-rgb"sv)
return CSSColorValue::ColorType::ProPhotoRGB;
if (color_space == "rec2020"sv)
return CSSColorValue::ColorType::Rec2020;
if (color_space == "xyz-d50"sv)
return CSSColorValue::ColorType::XYZD50;
if (color_space == "xyz"sv || color_space == "xyz-d65")
@ -88,6 +90,9 @@ Color CSSColor::to_color(Optional<Layout::NodeWithStyle const&>) const
if (color_type() == ColorType::ProPhotoRGB)
return Color::from_pro_photo_rgb(c1, c2, c3, alpha_val);
if (color_type() == ColorType::Rec2020)
return Color::from_rec2020(c1, c2, c3, alpha_val);
if (color_type() == ColorType::XYZD50)
return Color::from_xyz50(c1, c2, c3, alpha_val);

View file

@ -21,7 +21,7 @@ public:
virtual Color to_color(Optional<Layout::NodeWithStyle const&>) const override;
virtual String to_string() const override;
static constexpr Array s_supported_color_space = { "a98-rgb"sv, "display-p3"sv, "srgb"sv, "srgb-linear"sv, "prophoto-rgb"sv, "xyz"sv, "xyz-d50"sv, "xyz-d65"sv };
static constexpr Array s_supported_color_space = { "a98-rgb"sv, "display-p3"sv, "srgb"sv, "srgb-linear"sv, "prophoto-rgb"sv, "rec2020"sv, "xyz"sv, "xyz-d50"sv, "xyz-d65"sv };
private:
CSSColor(ColorType color_type, ValueComparingNonnullRefPtr<CSSStyleValue> c1, ValueComparingNonnullRefPtr<CSSStyleValue> c2, ValueComparingNonnullRefPtr<CSSStyleValue> c3, ValueComparingNonnullRefPtr<CSSStyleValue> alpha)

View file

@ -35,6 +35,7 @@ public:
sRGB, // This is used by CSSColor for color(srgb ...).
sRGBLinear,
ProPhotoRGB,
Rec2020,
XYZD50,
XYZD65,
};

View file

@ -0,0 +1,11 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS Color 4: CSS Color 4: rec2020</title>
<style>
body { background-color: grey; }
.test { background-color: rgb(99.993% 100% 100%); width: 12em; height: 12em; } /* color(rec2020 1 1 1) converted to sRGB */
</style>
<body>
<p>Test passes if you see a single square, and not two rectangles of different colors.</p>
<div class="test"></div>
</body>

View file

@ -0,0 +1,10 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS Color 4: CSS Color 4: rec2020</title>
<style>
.test { background-color: lab(85.7729% -160.7259 109.2319); width: 12em; height: 12em; } /* color(rec2020 0 1 0) converted to Lab */
</style>
<body>
<p>Test passes if you see a single square, and not two rectangles of different colors.</p>
<div class="test"></div>
</body>

View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS Color 4: predefined colorspaces, rec2020, decimal values</title>
<link rel="author" title="Chris Lilley" href="mailto:chris@w3.org">
<link rel="help" href="https://drafts.csswg.org/css-color-4/#predefined">
<link rel="match" href="../../../../expected/wpt-import/css/css-color/greensquare-090-ref.html">
<meta name="assert" content="Color function with explicit rec2020 value as decimal matches sRGB #009900">
<style>
.test { background-color: red; width: 12em; height: 6em; margin-top:0}
.ref { background-color: #009900; width: 12em; height: 6em; margin-bottom: 0}
.test {background-color: color(rec2020 0.299218 0.533327 0.120785)}
</style>
<body>
<p>Test passes if you see a green square, and no red.</p>
<p class="ref"> </p>
<p class="test"> </p>
</body>

View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS Color 4: predefined colorspaces, rec2020, percent values</title>
<link rel="author" title="Chris Lilley" href="mailto:chris@w3.org">
<link rel="help" href="https://drafts.csswg.org/css-color-4/#predefined">
<link rel="match" href="../../../../expected/wpt-import/css/css-color/greensquare-090-ref.html">
<meta name="assert" content="Color function with explicit rec2020 value as percent matches sRGB #009900">
<style>
.test { background-color: red; width: 12em; height: 6em; margin-top:0}
.ref { background-color: #009900; width: 12em; height: 6em; margin-bottom: 0}
.test {background-color: color(rec2020 29.9218% 53.3327% 12.0785%)}
</style>
<body>
<p>Test passes if you see a green square, and no red.</p>
<p class="ref"> </p>
<p class="test"> </p>
</body>

View file

@ -0,0 +1,15 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS Color 4: rec2020</title>
<link rel="author" title="Sam Weinig" href="mailto:weinig@apple.com">
<link rel="help" href="https://drafts.csswg.org/css-color-4/#valdef-color-rec2020">
<link rel="match" href="../../../../expected/wpt-import/css/css-color/greensquare-ref.html">
<meta name="assert" content="rec2020 with no alpha">
<style>
.test { background-color: red; width: 12em; height: 12em; }
.test { background-color: color(rec2020 0.235202 0.431704 0.085432); } /* green (sRGB #008000) converted to rec2020 */
</style>
<body>
<p>Test passes if you see a green square, and no red.</p>
<div class="test"></div>
</body>

View file

@ -0,0 +1,15 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS Color 4: rec2020</title>
<link rel="author" title="Sam Weinig" href="mailto:weinig@apple.com">
<link rel="help" href="https://drafts.csswg.org/css-color-4/#valdef-color-rec2020">
<link rel="match" href="../../../../expected/wpt-import/css/css-color/blacksquare-ref.html">
<meta name="assert" content="rec2020 with no alpha">
<style>
.test { background-color: red; width: 12em; height: 12em; }
.test { background-color: color(rec2020 0 0 0); } /* black (sRGB #000000) converted to rec2020 */
</style>
<body>
<p>Test passes if you see a black square, and no red.</p>
<div class="test"></div>
</body>

View file

@ -0,0 +1,18 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS Color 4: rec2020</title>
<link rel="author" title="Sam Weinig" href="mailto:weinig@apple.com">
<link rel="help" href="https://drafts.csswg.org/css-color-4/#valdef-color-rec2020">
<link rel="match" href="../../../../expected/wpt-import/css/css-color/rec2020-003-ref.html">
<meta name="assert" content="rec2020 with no alpha">
<style>
body { background-color: grey; }
.test { background-color: red; width: 12em; height: 6em; margin-top: 0; }
.ref { background-color: rgb(99.993% 100% 100%); width: 12em; height: 6em; margin-bottom: 0; } /* color(rec2020 1 1 1) converted to sRGB */
.test { background-color: color(rec2020 1 1 1); }
</style>
<body>
<p>Test passes if you see a single square, and not two rectangles of different colors.</p>
<div class="ref"></div>
<div class="test"></div>
</body>

View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS Color 4: rec2020</title>
<link rel="author" title="Sam Weinig" href="mailto:weinig@apple.com">
<link rel="help" href="https://drafts.csswg.org/css-color-4/#valdef-color-rec2020">
<link rel="match" href="../../../../expected/wpt-import/css/css-color/rec2020-004-ref.html">
<meta name="assert" content="rec2020 with no alpha">
<style>
.test { background-color: red; width: 12em; height: 6em; margin-top: 0; }
.ref { background-color: lab(85.7729% -160.7259 109.2319); width: 12em; height: 6em; margin-bottom: 0; } /* color(rec2020 0 1 0) converted to Lab */
.test { background-color: color(rec2020 0 1 0); }
</style>
<body>
<p>Test passes if you see a single square, and not two rectangles of different colors.</p>
<div class="ref"></div>
<div class="test"></div>
</body>

View file

@ -0,0 +1,15 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS Color 4: rec2020</title>
<link rel="author" title="Sam Weinig" href="mailto:weinig@apple.com">
<link rel="help" href="https://drafts.csswg.org/css-color-4/#valdef-color-rec2020">
<link rel="match" href="../../../../expected/wpt-import/css/css-color/greensquare-display-p3-ref.html">
<meta name="assert" content="rec2020 outside the sRGB gamut">
<style>
.test { background-color: red; width: 12em; height: 12em; }
.test { background-color: color(rec2020 0.431836 0.970723 0.079208); } /* green color(display-p3 0 1 0) converted to rec2020 */
</style>
<body>
<p>Test passes if you see a green square, and no red.</p>
<div class="test"></div>
</body>