LibWeb/CSS: Introduce CSSNumericValue and CSSUnitValue type stubs

CSS-Typed-OM has the following hierarchy:

CSSStyleValue
- CSSNumericValue
  - CSSUnitValue
  - CSSMathValue
    - ...various math functions...

Somewhat unintuitively, numbers are also stored using CSSUnitValue with
`unit = "number"`.

There are no distinct classes for LengthStyleValue, etc in the spec, but
they're convenient for us, so they are implemented as subclasses of
CSSUnitValue, at least for now.
This commit is contained in:
Sam Atkins 2024-08-14 16:25:48 +01:00 committed by Sam Atkins
parent 4771a08d27
commit 8952764267
Notes: github-actions[bot] 2024-08-21 09:53:21 +00:00
20 changed files with 225 additions and 107 deletions

View file

@ -33,6 +33,7 @@ public:
Type type() const { return m_type; }
double raw_value() const { return m_value; }
StringView unit_name() const;
bool operator==(Angle const& other) const
{
@ -54,8 +55,6 @@ public:
static Angle resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&, Angle const& reference_value);
private:
StringView unit_name() const;
Type m_type;
double m_value { 0 };
};

View file

@ -30,6 +30,7 @@ public:
Type type() const { return m_type; }
double raw_value() const { return m_value; }
StringView unit_name() const;
bool operator==(Flex const& other) const
{
@ -49,8 +50,6 @@ public:
}
private:
StringView unit_name() const;
Type m_type;
double m_value { 0 };
};

View file

@ -28,6 +28,7 @@ public:
Type type() const { return m_type; }
double raw_value() const { return m_value; }
StringView unit_name() const;
bool operator==(Frequency const& other) const
{
@ -49,8 +50,6 @@ public:
static Frequency resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&, Frequency const& reference_value);
private:
StringView unit_name() const;
Type m_type;
double m_value { 0 };
};

View file

@ -187,97 +187,97 @@ String Length::to_string() const
return MUST(String::formatted("{:.5}{}", m_value, unit_name()));
}
char const* Length::unit_name() const
StringView Length::unit_name() const
{
switch (m_type) {
case Type::Em:
return "em";
return "em"sv;
case Type::Rem:
return "rem";
return "rem"sv;
case Type::Ex:
return "ex";
return "ex"sv;
case Type::Rex:
return "rex";
return "rex"sv;
case Type::Cap:
return "cap";
return "cap"sv;
case Type::Rcap:
return "rcap";
return "rcap"sv;
case Type::Ch:
return "ch";
return "ch"sv;
case Type::Rch:
return "rch";
return "rch"sv;
case Type::Ic:
return "ic";
return "ic"sv;
case Type::Ric:
return "ric";
return "ric"sv;
case Type::Lh:
return "lh";
return "lh"sv;
case Type::Rlh:
return "rlh";
return "rlh"sv;
case Type::Vw:
return "vw";
return "vw"sv;
case Type::Svw:
return "svw";
return "svw"sv;
case Type::Lvw:
return "lvw";
return "lvw"sv;
case Type::Dvw:
return "dvw";
return "dvw"sv;
case Type::Vh:
return "vh";
return "vh"sv;
case Type::Svh:
return "svh";
return "svh"sv;
case Type::Lvh:
return "lvh";
return "lvh"sv;
case Type::Dvh:
return "dvh";
return "dvh"sv;
case Type::Vi:
return "vi";
return "vi"sv;
case Type::Svi:
return "svi";
return "svi"sv;
case Type::Lvi:
return "lvi";
return "lvi"sv;
case Type::Dvi:
return "dvi";
return "dvi"sv;
case Type::Vb:
return "vb";
return "vb"sv;
case Type::Svb:
return "svb";
return "svb"sv;
case Type::Lvb:
return "lvb";
return "lvb"sv;
case Type::Dvb:
return "dvb";
return "dvb"sv;
case Type::Vmin:
return "vmin";
return "vmin"sv;
case Type::Svmin:
return "svmin";
return "svmin"sv;
case Type::Lvmin:
return "lvmin";
return "lvmin"sv;
case Type::Dvmin:
return "dvmin";
return "dvmin"sv;
case Type::Vmax:
return "vmax";
return "vmax"sv;
case Type::Svmax:
return "svmax";
return "svmax"sv;
case Type::Lvmax:
return "lvmax";
return "lvmax"sv;
case Type::Dvmax:
return "dvmax";
return "dvmax"sv;
case Type::Cm:
return "cm";
return "cm"sv;
case Type::Mm:
return "mm";
return "mm"sv;
case Type::Q:
return "Q";
return "Q"sv;
case Type::In:
return "in";
return "in"sv;
case Type::Pt:
return "pt";
return "pt"sv;
case Type::Pc:
return "pc";
return "pc"sv;
case Type::Px:
return "px";
return "px"sv;
case Type::Auto:
return "auto";
return "auto"sv;
}
VERIFY_NOT_REACHED();
}

View file

@ -155,6 +155,7 @@ public:
Type type() const { return m_type; }
double raw_value() const { return m_value; }
StringView unit_name() const;
struct ResolutionContext {
[[nodiscard]] static Length::ResolutionContext for_layout_node(Layout::Node const&);
@ -226,8 +227,6 @@ public:
static Length resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&, CSSPixels reference_value);
private:
char const* unit_name() const;
[[nodiscard]] CSSPixels to_px_slow_case(Layout::Node const&) const;
Type m_type;

View file

@ -29,6 +29,7 @@ public:
Type type() const { return m_type; }
double raw_value() const { return m_value; }
StringView unit_name() const;
bool operator==(Resolution const& other) const
{
@ -48,8 +49,6 @@ public:
}
private:
StringView unit_name() const;
Type m_type;
double m_value { 0 };
};

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021-2023, Sam Atkins <atkinssj@serenityos.org>
* Copyright (c) 2021-2024, Sam Atkins <sam@ladybird.org>
* Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org>
* Copyright (c) 2022-2023, MacDue <macdue@dueutil.tech>
*
@ -12,7 +12,7 @@
namespace Web::CSS {
AngleStyleValue::AngleStyleValue(Angle angle)
: StyleValueWithDefaultOperators(Type::Angle)
: CSSUnitValue(Type::Angle)
, m_angle(move(angle))
{
}
@ -24,9 +24,12 @@ String AngleStyleValue::to_string() const
return m_angle.to_string();
}
bool AngleStyleValue::properties_equal(AngleStyleValue const& other) const
bool AngleStyleValue::equals(CSSStyleValue const& other) const
{
return m_angle == other.m_angle;
if (type() != other.type())
return false;
auto const& other_angle = other.as_angle();
return m_angle == other_angle.m_angle;
}
}

View file

@ -1,7 +1,7 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org>
* Copyright (c) 2021-2023, Sam Atkins <atkinssj@serenityos.org>
* Copyright (c) 2021-2024, Sam Atkins <sam@ladybird.org>
* Copyright (c) 2022-2023, MacDue <macdue@dueutil.tech>
*
* SPDX-License-Identifier: BSD-2-Clause
@ -10,11 +10,11 @@
#pragma once
#include <LibWeb/CSS/Angle.h>
#include <LibWeb/CSS/CSSStyleValue.h>
#include <LibWeb/CSS/StyleValues/CSSUnitValue.h>
namespace Web::CSS {
class AngleStyleValue : public StyleValueWithDefaultOperators<AngleStyleValue> {
class AngleStyleValue : public CSSUnitValue {
public:
static ValueComparingNonnullRefPtr<AngleStyleValue> create(Angle angle)
{
@ -23,10 +23,12 @@ public:
virtual ~AngleStyleValue() override;
Angle const& angle() const { return m_angle; }
virtual double value() const override { return m_angle.raw_value(); }
virtual StringView unit() const override { return m_angle.unit_name(); }
virtual String to_string() const override;
bool properties_equal(AngleStyleValue const& other) const;
bool equals(CSSStyleValue const& other) const override;
private:
explicit AngleStyleValue(Angle angle);

View file

@ -0,0 +1,25 @@
/*
* Copyright (c) 2024, Sam Atkins <sam@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/CSS/CSSStyleValue.h>
namespace Web::CSS {
// https://drafts.css-houdini.org/css-typed-om-1/#cssnumericvalue
class CSSNumericValue : public CSSStyleValue {
public:
virtual ~CSSNumericValue() override = default;
protected:
explicit CSSNumericValue(Type type)
: CSSStyleValue(type)
{
}
};
}

View file

@ -0,0 +1,29 @@
/*
* Copyright (c) 2024, Sam Atkins <sam@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/FlyString.h>
#include <LibWeb/CSS/StyleValues/CSSNumericValue.h>
namespace Web::CSS {
// https://drafts.css-houdini.org/css-typed-om-1/#cssunitvalue
class CSSUnitValue : public CSSNumericValue {
public:
virtual ~CSSUnitValue() override = default;
virtual double value() const = 0;
virtual StringView unit() const = 0;
protected:
explicit CSSUnitValue(Type type)
: CSSNumericValue(type)
{
}
};
}

View file

@ -1,17 +1,17 @@
/*
* Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org>
* Copyright (c) 2023-2024, Sam Atkins <sam@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/CSS/CSSStyleValue.h>
#include <LibWeb/CSS/Flex.h>
#include <LibWeb/CSS/StyleValues/CSSUnitValue.h>
namespace Web::CSS {
class FlexStyleValue final : public StyleValueWithDefaultOperators<FlexStyleValue> {
class FlexStyleValue final : public CSSUnitValue {
public:
static ValueComparingNonnullRefPtr<FlexStyleValue> create(Flex flex)
{
@ -20,15 +20,22 @@ public:
virtual ~FlexStyleValue() override = default;
Flex const& flex() const { return m_flex; }
Flex& flex() { return m_flex; }
virtual double value() const override { return m_flex.raw_value(); }
virtual StringView unit() const override { return m_flex.unit_name(); }
virtual String to_string() const override { return m_flex.to_string(); }
bool properties_equal(FlexStyleValue const& other) const { return m_flex == other.m_flex; }
bool equals(CSSStyleValue const& other) const override
{
if (type() != other.type())
return false;
auto const& other_flex = other.as_flex();
return m_flex == other_flex.m_flex;
}
private:
FlexStyleValue(Flex&& flex)
: StyleValueWithDefaultOperators(Type::Flex)
: CSSUnitValue(Type::Flex)
, m_flex(flex)
{
}

View file

@ -1,7 +1,7 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org>
* Copyright (c) 2021-2023, Sam Atkins <atkinssj@serenityos.org>
* Copyright (c) 2021-2024, Sam Atkins <sam@ladybird.org>
* Copyright (c) 2022-2023, MacDue <macdue@dueutil.tech>
*
* SPDX-License-Identifier: BSD-2-Clause
@ -9,12 +9,12 @@
#pragma once
#include <LibWeb/CSS/CSSStyleValue.h>
#include <LibWeb/CSS/Frequency.h>
#include <LibWeb/CSS/StyleValues/CSSUnitValue.h>
namespace Web::CSS {
class FrequencyStyleValue : public StyleValueWithDefaultOperators<FrequencyStyleValue> {
class FrequencyStyleValue final : public CSSUnitValue {
public:
static ValueComparingNonnullRefPtr<FrequencyStyleValue> create(Frequency frequency)
{
@ -23,14 +23,22 @@ public:
virtual ~FrequencyStyleValue() override = default;
Frequency const& frequency() const { return m_frequency; }
virtual double value() const override { return m_frequency.raw_value(); }
virtual StringView unit() const override { return m_frequency.unit_name(); }
virtual String to_string() const override { return m_frequency.to_string(); }
bool properties_equal(FrequencyStyleValue const& other) const { return m_frequency == other.m_frequency; }
bool equals(CSSStyleValue const& other) const override
{
if (type() != other.type())
return false;
auto const& other_frequency = other.as_frequency();
return m_frequency == other_frequency.m_frequency;
}
private:
explicit FrequencyStyleValue(Frequency frequency)
: StyleValueWithDefaultOperators(Type::Frequency)
: CSSUnitValue(Type::Frequency)
, m_frequency(move(frequency))
{
}

View file

@ -1,16 +1,16 @@
/*
* Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org>
* Copyright (c) 2023-2024, Sam Atkins <sam@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/CSS/CSSStyleValue.h>
#include <LibWeb/CSS/StyleValues/CSSUnitValue.h>
namespace Web::CSS {
class IntegerStyleValue : public StyleValueWithDefaultOperators<IntegerStyleValue> {
class IntegerStyleValue final : public CSSUnitValue {
public:
static ValueComparingNonnullRefPtr<IntegerStyleValue> create(i64 value)
{
@ -18,14 +18,22 @@ public:
}
i64 integer() const { return m_value; }
virtual double value() const override { return m_value; }
virtual StringView unit() const override { return "number"sv; }
virtual String to_string() const override;
bool properties_equal(IntegerStyleValue const& other) const { return m_value == other.m_value; }
bool equals(CSSStyleValue const& other) const override
{
if (type() != other.type())
return false;
auto const& other_integer = other.as_integer();
return m_value == other_integer.m_value;
}
private:
explicit IntegerStyleValue(i64 value)
: StyleValueWithDefaultOperators(Type::Integer)
: CSSUnitValue(Type::Integer)
, m_value(value)
{
}

View file

@ -34,4 +34,12 @@ ValueComparingNonnullRefPtr<CSSStyleValue const> LengthStyleValue::absolutized(C
return *this;
}
bool LengthStyleValue::equals(CSSStyleValue const& other) const
{
if (type() != other.type())
return false;
auto const& other_length = other.as_length();
return m_length == other_length.m_length;
}
}

View file

@ -1,7 +1,7 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org>
* Copyright (c) 2021-2023, Sam Atkins <atkinssj@serenityos.org>
* Copyright (c) 2021-2024, Sam Atkins <sam@ladybird.org>
* Copyright (c) 2022-2023, MacDue <macdue@dueutil.tech>
*
* SPDX-License-Identifier: BSD-2-Clause
@ -9,25 +9,28 @@
#pragma once
#include <LibWeb/CSS/CSSStyleValue.h>
#include <LibWeb/CSS/Length.h>
#include <LibWeb/CSS/StyleValues/CSSUnitValue.h>
namespace Web::CSS {
class LengthStyleValue : public StyleValueWithDefaultOperators<LengthStyleValue> {
class LengthStyleValue final : public CSSUnitValue {
public:
static ValueComparingNonnullRefPtr<LengthStyleValue> create(Length const&);
virtual ~LengthStyleValue() override = default;
Length const& length() const { return m_length; }
virtual double value() const override { return m_length.raw_value(); }
virtual StringView unit() const override { return m_length.unit_name(); }
virtual String to_string() const override { return m_length.to_string(); }
virtual ValueComparingNonnullRefPtr<CSSStyleValue const> absolutized(CSSPixelRect const& viewport_rect, Length::FontMetrics const& font_metrics, Length::FontMetrics const& root_font_metrics) const override;
bool properties_equal(LengthStyleValue const& other) const { return m_length == other.m_length; }
bool equals(CSSStyleValue const& other) const override;
private:
explicit LengthStyleValue(Length const& length)
: StyleValueWithDefaultOperators(Type::Length)
: CSSUnitValue(Type::Length)
, m_length(length)
{
}

View file

@ -1,7 +1,7 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org>
* Copyright (c) 2021-2023, Sam Atkins <atkinssj@serenityos.org>
* Copyright (c) 2021-2024, Sam Atkins <sam@ladybird.org>
* Copyright (c) 2022-2023, MacDue <macdue@dueutil.tech>
*
* SPDX-License-Identifier: BSD-2-Clause
@ -9,11 +9,11 @@
#pragma once
#include <LibWeb/CSS/CSSStyleValue.h>
#include <LibWeb/CSS/StyleValues/CSSUnitValue.h>
namespace Web::CSS {
class NumberStyleValue : public StyleValueWithDefaultOperators<NumberStyleValue> {
class NumberStyleValue final : public CSSUnitValue {
public:
static ValueComparingNonnullRefPtr<NumberStyleValue> create(double value)
{
@ -21,14 +21,22 @@ public:
}
double number() const { return m_value; }
virtual double value() const override { return m_value; }
virtual StringView unit() const override { return "number"sv; }
virtual String to_string() const override;
bool properties_equal(NumberStyleValue const& other) const { return m_value == other.m_value; }
bool equals(CSSStyleValue const& other) const override
{
if (type() != other.type())
return false;
auto const& other_number = other.as_number();
return m_value == other_number.m_value;
}
private:
explicit NumberStyleValue(double value)
: StyleValueWithDefaultOperators(Type::Number)
: CSSUnitValue(Type::Number)
, m_value(value)
{
}

View file

@ -1,7 +1,7 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org>
* Copyright (c) 2021-2023, Sam Atkins <atkinssj@serenityos.org>
* Copyright (c) 2021-2024, Sam Atkins <sam@ladybird.org>
* Copyright (c) 2022-2023, MacDue <macdue@dueutil.tech>
*
* SPDX-License-Identifier: BSD-2-Clause
@ -9,12 +9,12 @@
#pragma once
#include <LibWeb/CSS/CSSStyleValue.h>
#include <LibWeb/CSS/Percentage.h>
#include <LibWeb/CSS/StyleValues/CSSUnitValue.h>
namespace Web::CSS {
class PercentageStyleValue final : public StyleValueWithDefaultOperators<PercentageStyleValue> {
class PercentageStyleValue final : public CSSUnitValue {
public:
static ValueComparingNonnullRefPtr<PercentageStyleValue> create(Percentage percentage)
{
@ -23,15 +23,22 @@ public:
virtual ~PercentageStyleValue() override = default;
Percentage const& percentage() const { return m_percentage; }
Percentage& percentage() { return m_percentage; }
virtual double value() const override { return m_percentage.value(); }
virtual StringView unit() const override { return "percent"sv; }
virtual String to_string() const override { return m_percentage.to_string(); }
bool properties_equal(PercentageStyleValue const& other) const { return m_percentage == other.m_percentage; }
bool equals(CSSStyleValue const& other) const override
{
if (type() != other.type())
return false;
auto const& other_percentage = other.as_percentage();
return m_percentage == other_percentage.m_percentage;
}
private:
PercentageStyleValue(Percentage&& percentage)
: StyleValueWithDefaultOperators(Type::Percentage)
: CSSUnitValue(Type::Percentage)
, m_percentage(percentage)
{
}

View file

@ -1,17 +1,17 @@
/*
* Copyright (c) 2022-2023, Sam Atkins <atkinssj@serenityos.org>
* Copyright (c) 2022-2024, Sam Atkins <sam@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/CSS/CSSStyleValue.h>
#include <LibWeb/CSS/Resolution.h>
#include <LibWeb/CSS/StyleValues/CSSUnitValue.h>
namespace Web::CSS {
class ResolutionStyleValue : public StyleValueWithDefaultOperators<ResolutionStyleValue> {
class ResolutionStyleValue : public CSSUnitValue {
public:
static ValueComparingNonnullRefPtr<ResolutionStyleValue> create(Resolution resolution)
{
@ -20,14 +20,22 @@ public:
virtual ~ResolutionStyleValue() override = default;
Resolution const& resolution() const { return m_resolution; }
virtual double value() const override { return m_resolution.raw_value(); }
virtual StringView unit() const override { return m_resolution.unit_name(); }
virtual String to_string() const override { return m_resolution.to_string(); }
bool properties_equal(ResolutionStyleValue const& other) const { return m_resolution == other.m_resolution; }
bool equals(CSSStyleValue const& other) const override
{
if (type() != other.type())
return false;
auto const& other_resolution = other.as_resolution();
return m_resolution == other_resolution.m_resolution;
}
private:
explicit ResolutionStyleValue(Resolution resolution)
: StyleValueWithDefaultOperators(Type::Resolution)
: CSSUnitValue(Type::Resolution)
, m_resolution(move(resolution))
{
}

View file

@ -1,7 +1,7 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org>
* Copyright (c) 2021-2023, Sam Atkins <atkinssj@serenityos.org>
* Copyright (c) 2021-2024, Sam Atkins <sam@ladybird.org>
* Copyright (c) 2022-2023, MacDue <macdue@dueutil.tech>
*
* SPDX-License-Identifier: BSD-2-Clause
@ -9,12 +9,12 @@
#pragma once
#include <LibWeb/CSS/CSSStyleValue.h>
#include <LibWeb/CSS/StyleValues/CSSUnitValue.h>
#include <LibWeb/CSS/Time.h>
namespace Web::CSS {
class TimeStyleValue : public StyleValueWithDefaultOperators<TimeStyleValue> {
class TimeStyleValue : public CSSUnitValue {
public:
static ValueComparingNonnullRefPtr<TimeStyleValue> create(Time time)
{
@ -23,14 +23,22 @@ public:
virtual ~TimeStyleValue() override = default;
Time const& time() const { return m_time; }
virtual double value() const override { return m_time.raw_value(); }
virtual StringView unit() const override { return m_time.unit_name(); }
virtual String to_string() const override { return m_time.to_string(); }
bool properties_equal(TimeStyleValue const& other) const { return m_time == other.m_time; }
bool equals(CSSStyleValue const& other) const override
{
if (type() != other.type())
return false;
auto const& other_time = other.as_time();
return m_time == other_time.m_time;
}
private:
explicit TimeStyleValue(Time time)
: StyleValueWithDefaultOperators(Type::Time)
: CSSUnitValue(Type::Time)
, m_time(move(time))
{
}

View file

@ -30,6 +30,7 @@ public:
Type type() const { return m_type; }
double raw_value() const { return m_value; }
StringView unit_name() const;
bool operator==(Time const& other) const
{
@ -51,8 +52,6 @@ public:
static Time resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&, Time const& reference_value);
private:
StringView unit_name() const;
Type m_type;
double m_value { 0 };
};