LibWeb/CSS: Replace CSSUnitValue with DimensionStyleValue

CSSUnitValue is a typed-om type which we will implement separately in
the future. However, it still seems useful to give our dimension values
a base class. (Maybe they could be templated in the future?) So instead
of deleting it entirely, rename it to DimensionStyleValue and make its
API match our style better.
This commit is contained in:
Sam Atkins 2025-08-08 11:08:54 +01:00 committed by Tim Ledbetter
commit 99bce9a94d
Notes: github-actions[bot] 2025-08-08 14:20:30 +00:00
17 changed files with 65 additions and 52 deletions

View file

@ -133,13 +133,13 @@ Parser::ParseErrorOr<NonnullRefPtr<StyleValue const>> Parser::parse_descriptor_v
// <length [0,∞]>{1,2}
if (auto first_length = parse_length_value(tokens)) {
if (first_length->is_length() && first_length->as_length().length().raw_value() < 0)
if (first_length->is_length() && first_length->as_length().raw_value() < 0)
return nullptr;
tokens.discard_whitespace();
if (auto second_length = parse_length_value(tokens)) {
if (second_length->is_length() && second_length->as_length().length().raw_value() < 0)
if (second_length->is_length() && second_length->as_length().raw_value() < 0)
return nullptr;
return StyleValueList::create(StyleValueVector { first_length.release_nonnull(), second_length.release_nonnull() }, StyleValueList::Separator::Space);
@ -186,7 +186,7 @@ Parser::ParseErrorOr<NonnullRefPtr<StyleValue const>> Parser::parse_descriptor_v
case DescriptorMetadata::ValueType::PositivePercentage: {
if (auto percentage_value = parse_percentage_value(tokens)) {
if (percentage_value->is_percentage()) {
if (percentage_value->as_percentage().value() < 0)
if (percentage_value->as_percentage().raw_value() < 0)
return nullptr;
return percentage_value.release_nonnull();
}

View file

@ -2032,9 +2032,9 @@ RefPtr<StyleValue const> Parser::parse_single_shadow_value(TokenStream<Component
if (!maybe_blur_radius)
continue;
blur_radius = maybe_blur_radius;
if (blur_radius->is_length() && blur_radius->as_length().length().raw_value() < 0)
if (blur_radius->is_length() && blur_radius->as_length().raw_value() < 0)
return nullptr;
if (blur_radius->is_percentage() && blur_radius->as_percentage().value() < 0)
if (blur_radius->is_percentage() && blur_radius->as_percentage().raw_value() < 0)
return nullptr;
tokens.discard_a_token();
@ -2189,9 +2189,9 @@ RefPtr<StyleValue const> Parser::parse_stroke_dasharray_value(TokenStream<Compon
auto value = parse_length_percentage_value(tokens);
if (!value)
return {};
if (value->is_percentage() && value->as_percentage().value() < 0)
if (value->is_percentage() && value->as_percentage().raw_value() < 0)
return {};
if (value->is_length() && value->as_length().length().raw_value() < 0)
if (value->is_length() && value->as_length().raw_value() < 0)
return {};
dashes.append(value.release_nonnull());
}

View file

@ -12,7 +12,7 @@
namespace Web::CSS {
AngleStyleValue::AngleStyleValue(Angle angle)
: CSSUnitValue(Type::Angle)
: DimensionStyleValue(Type::Angle)
, m_angle(move(angle))
{
}

View file

@ -10,11 +10,11 @@
#pragma once
#include <LibWeb/CSS/Angle.h>
#include <LibWeb/CSS/StyleValues/CSSUnitValue.h>
#include <LibWeb/CSS/StyleValues/DimensionStyleValue.h>
namespace Web::CSS {
class AngleStyleValue : public CSSUnitValue {
class AngleStyleValue : public DimensionStyleValue {
public:
static ValueComparingNonnullRefPtr<AngleStyleValue const> create(Angle angle)
{
@ -23,8 +23,8 @@ 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 double raw_value() const override { return m_angle.raw_value(); }
virtual StringView unit_name() const override { return m_angle.unit_name(); }
virtual String to_string(SerializationMode) const override;

View file

@ -28,7 +28,7 @@ Optional<Color> CSSRGB::to_color(ColorResolutionContext color_resolution_context
return normalized(style_value.as_number().number());
if (style_value.is_percentage())
return normalized(style_value.as_percentage().value() * 255 / 100);
return normalized(style_value.as_percentage().raw_value() * 255 / 100);
if (style_value.is_calculated()) {
auto const& calculated = style_value.as_calculated();

View file

@ -105,7 +105,7 @@ String ColorFunctionStyleValue::to_string(SerializationMode mode) const
{
auto convert_percentage = [&](ValueComparingNonnullRefPtr<StyleValue const> const& value) -> RemoveReference<decltype(value)> {
if (value->is_percentage())
return NumberStyleValue::create(value->as_percentage().value() / 100);
return NumberStyleValue::create(value->as_percentage().raw_value() / 100);
if (mode == SerializationMode::ResolvedValue && value->is_calculated()) {
// FIXME: Figure out how to get the proper calculation resolution context here
CalculationResolutionContext context {};

View file

@ -13,20 +13,19 @@
namespace Web::CSS {
// https://drafts.css-houdini.org/css-typed-om-1/#cssunitvalue
class CSSUnitValue : public StyleValue {
class DimensionStyleValue : public StyleValue {
public:
virtual ~CSSUnitValue() override = default;
virtual ~DimensionStyleValue() override = default;
virtual double value() const = 0;
virtual StringView unit() const = 0;
virtual double raw_value() const = 0;
virtual StringView unit_name() const = 0;
virtual Vector<Parser::ComponentValue> tokenize() const override
{
return { Parser::Token::create_dimension(value(), FlyString::from_utf8_without_validation(unit().bytes())) };
return { Parser::Token::create_dimension(raw_value(), FlyString::from_utf8_without_validation(unit_name().bytes())) };
}
protected:
explicit CSSUnitValue(Type type)
explicit DimensionStyleValue(Type type)
: StyleValue(type)
{
}

View file

@ -7,11 +7,11 @@
#pragma once
#include <LibWeb/CSS/Flex.h>
#include <LibWeb/CSS/StyleValues/CSSUnitValue.h>
#include <LibWeb/CSS/StyleValues/DimensionStyleValue.h>
namespace Web::CSS {
class FlexStyleValue final : public CSSUnitValue {
class FlexStyleValue final : public DimensionStyleValue {
public:
static ValueComparingNonnullRefPtr<FlexStyleValue const> create(Flex flex)
{
@ -20,8 +20,8 @@ public:
virtual ~FlexStyleValue() override = default;
Flex const& flex() const { return m_flex; }
virtual double value() const override { return m_flex.raw_value(); }
virtual StringView unit() const override { return m_flex.unit_name(); }
virtual double raw_value() const override { return m_flex.raw_value(); }
virtual StringView unit_name() const override { return m_flex.unit_name(); }
virtual String to_string(SerializationMode serialization_mode) const override { return m_flex.to_string(serialization_mode); }
@ -35,7 +35,7 @@ public:
private:
FlexStyleValue(Flex&& flex)
: CSSUnitValue(Type::Flex)
: DimensionStyleValue(Type::Flex)
, m_flex(flex)
{
}

View file

@ -10,11 +10,11 @@
#pragma once
#include <LibWeb/CSS/Frequency.h>
#include <LibWeb/CSS/StyleValues/CSSUnitValue.h>
#include <LibWeb/CSS/StyleValues/DimensionStyleValue.h>
namespace Web::CSS {
class FrequencyStyleValue final : public CSSUnitValue {
class FrequencyStyleValue final : public DimensionStyleValue {
public:
static ValueComparingNonnullRefPtr<FrequencyStyleValue const> create(Frequency frequency)
{
@ -23,8 +23,8 @@ 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 double raw_value() const override { return m_frequency.raw_value(); }
virtual StringView unit_name() const override { return m_frequency.unit_name(); }
virtual String to_string(SerializationMode serialization_mode) const override { return m_frequency.to_string(serialization_mode); }
@ -38,7 +38,7 @@ public:
private:
explicit FrequencyStyleValue(Frequency frequency)
: CSSUnitValue(Type::Frequency)
: DimensionStyleValue(Type::Frequency)
, m_frequency(move(frequency))
{
}

View file

@ -10,18 +10,18 @@
#pragma once
#include <LibWeb/CSS/Length.h>
#include <LibWeb/CSS/StyleValues/CSSUnitValue.h>
#include <LibWeb/CSS/StyleValues/DimensionStyleValue.h>
namespace Web::CSS {
class LengthStyleValue final : public CSSUnitValue {
class LengthStyleValue final : public DimensionStyleValue {
public:
static ValueComparingNonnullRefPtr<LengthStyleValue const> 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 double raw_value() const override { return m_length.raw_value(); }
virtual StringView unit_name() const override { return m_length.unit_name(); }
virtual String to_string(SerializationMode serialization_mode) const override { return m_length.to_string(serialization_mode); }
virtual ValueComparingNonnullRefPtr<StyleValue const> absolutized(CSSPixelRect const& viewport_rect, Length::FontMetrics const& font_metrics, Length::FontMetrics const& root_font_metrics) const override;
@ -30,7 +30,7 @@ public:
private:
explicit LengthStyleValue(Length const& length)
: CSSUnitValue(Type::Length)
: DimensionStyleValue(Type::Length)
, m_length(length)
{
}

View file

@ -10,11 +10,11 @@
#pragma once
#include <LibWeb/CSS/Percentage.h>
#include <LibWeb/CSS/StyleValues/CSSUnitValue.h>
#include <LibWeb/CSS/StyleValues/DimensionStyleValue.h>
namespace Web::CSS {
class PercentageStyleValue final : public CSSUnitValue {
class PercentageStyleValue final : public DimensionStyleValue {
public:
static ValueComparingNonnullRefPtr<PercentageStyleValue const> create(Percentage percentage)
{
@ -23,8 +23,8 @@ public:
virtual ~PercentageStyleValue() override = default;
Percentage const& percentage() const { return m_percentage; }
virtual double value() const override { return m_percentage.value(); }
virtual StringView unit() const override { return "percent"sv; }
virtual double raw_value() const override { return m_percentage.value(); }
virtual StringView unit_name() const override { return "percent"sv; }
virtual String to_string(SerializationMode) const override { return m_percentage.to_string(); }
@ -38,7 +38,7 @@ public:
private:
PercentageStyleValue(Percentage&& percentage)
: CSSUnitValue(Type::Percentage)
: DimensionStyleValue(Type::Percentage)
, m_percentage(percentage)
{
}

View file

@ -7,11 +7,11 @@
#pragma once
#include <LibWeb/CSS/Resolution.h>
#include <LibWeb/CSS/StyleValues/CSSUnitValue.h>
#include <LibWeb/CSS/StyleValues/DimensionStyleValue.h>
namespace Web::CSS {
class ResolutionStyleValue : public CSSUnitValue {
class ResolutionStyleValue : public DimensionStyleValue {
public:
static ValueComparingNonnullRefPtr<ResolutionStyleValue const> create(Resolution resolution)
{
@ -20,8 +20,8 @@ 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 double raw_value() const override { return m_resolution.raw_value(); }
virtual StringView unit_name() const override { return m_resolution.unit_name(); }
virtual String to_string(SerializationMode serialization_mode) const override { return m_resolution.to_string(serialization_mode); }
@ -35,7 +35,7 @@ public:
private:
explicit ResolutionStyleValue(Resolution resolution)
: CSSUnitValue(Type::Resolution)
: DimensionStyleValue(Type::Resolution)
, m_resolution(move(resolution))
{
}

View file

@ -110,6 +110,12 @@ AbstractImageStyleValue const& StyleValue::as_abstract_image() const
return static_cast<AbstractImageStyleValue const&>(*this);
}
DimensionStyleValue const& StyleValue::as_dimension() const
{
VERIFY(is_dimension());
return static_cast<DimensionStyleValue const&>(*this);
}
#define __ENUMERATE_CSS_STYLE_VALUE_TYPE(title_case, snake_case, style_value_class_name) \
style_value_class_name const& StyleValue::as_##snake_case() const \
{ \

View file

@ -172,6 +172,13 @@ public:
AbstractImageStyleValue const& as_abstract_image() const;
AbstractImageStyleValue& as_abstract_image() { return const_cast<AbstractImageStyleValue&>(const_cast<StyleValue const&>(*this).as_abstract_image()); }
bool is_dimension() const
{
return first_is_one_of(type(), Type::Angle, Type::Flex, Type::Frequency, Type::Length, Type::Percentage, Type::Resolution, Type::Time);
}
DimensionStyleValue const& as_dimension() const;
DimensionStyleValue& as_dimension() { return const_cast<DimensionStyleValue&>(const_cast<StyleValue const&>(*this).as_dimension()); }
virtual bool is_color_function() const { return false; }
#define __ENUMERATE_CSS_STYLE_VALUE_TYPE(title_case, snake_case, style_value_class_name) \

View file

@ -9,12 +9,12 @@
#pragma once
#include <LibWeb/CSS/StyleValues/CSSUnitValue.h>
#include <LibWeb/CSS/StyleValues/DimensionStyleValue.h>
#include <LibWeb/CSS/Time.h>
namespace Web::CSS {
class TimeStyleValue : public CSSUnitValue {
class TimeStyleValue : public DimensionStyleValue {
public:
static ValueComparingNonnullRefPtr<TimeStyleValue const> create(Time time)
{
@ -23,8 +23,8 @@ 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 double raw_value() const override { return m_time.raw_value(); }
virtual StringView unit_name() const override { return m_time.unit_name(); }
virtual String to_string(SerializationMode serialization_mode) const override { return m_time.to_string(serialization_mode); }
@ -38,7 +38,7 @@ public:
private:
explicit TimeStyleValue(Time time)
: CSSUnitValue(Type::Time)
: DimensionStyleValue(Type::Time)
, m_time(move(time))
{
}

View file

@ -252,6 +252,7 @@ class CSSStyleSheet;
class CSSSupportsRule;
class CursorStyleValue;
class CustomIdentStyleValue;
class DimensionStyleValue;
class Display;
class DisplayStyleValue;
class EasingStyleValue;

View file

@ -5486,7 +5486,7 @@ RefPtr<CSS::StyleValue const> parse_nonzero_dimension_value(StringView string)
return nullptr;
// 4. If value is zero, return an error.
if (value->is_length() && value->as_length().length().raw_value() == 0)
if (value->is_length() && value->as_length().raw_value() == 0)
return nullptr;
if (value->is_percentage() && value->as_percentage().percentage().value() == 0)
return nullptr;