1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 15:57:45 +00:00

LibWeb: Introduce CalculatedOr type

This is intended as a replacement for Length and friends each holding a
`RefPtr<CalculatedStyleValue>`. Instead, let's make the types explicit
about whether they are calculated or not. This then means a Length is
always a Length, and won't require including `StyleValue.h`.

As noted, it's probably nicer for LengthOrCalculated to live in
`Length.h`, but we can't do that until Length stops including
`StyleValue.h`.
This commit is contained in:
Sam Atkins 2023-03-30 16:57:49 +01:00 committed by Andreas Kling
parent b727f8113f
commit fa90a3bb4f
5 changed files with 206 additions and 4 deletions

View file

@ -16,6 +16,7 @@ set(SOURCES
Crypto/Crypto.cpp
Crypto/SubtleCrypto.cpp
CSS/Angle.cpp
CSS/CalculatedOr.cpp
CSS/Clip.cpp
CSS/CSS.cpp
CSS/CSSConditionRule.cpp

View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "CalculatedOr.h"
namespace Web::CSS {
Angle AngleOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const&) const
{
return calculated->resolve_angle().value();
}
Frequency FrequencyOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const&) const
{
return calculated->resolve_frequency().value();
}
Length LengthOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const& layout_node) const
{
return calculated->resolve_length(layout_node).value();
}
Percentage PercentageOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const&) const
{
return calculated->resolve_percentage().value();
}
Time TimeOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const&) const
{
return calculated->resolve_time().value();
}
}

View file

@ -0,0 +1,155 @@
/*
* Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Variant.h>
#include <LibWeb/CSS/Angle.h>
#include <LibWeb/CSS/Frequency.h>
#include <LibWeb/CSS/Length.h>
#include <LibWeb/CSS/Percentage.h>
#include <LibWeb/CSS/StyleValue.h>
#include <LibWeb/CSS/Time.h>
namespace Web::CSS {
template<typename T>
class CalculatedOr {
public:
CalculatedOr(T t)
: m_value(move(t))
{
}
CalculatedOr(NonnullRefPtr<CalculatedStyleValue> calculated)
: m_value(move(calculated))
{
}
virtual ~CalculatedOr() = default;
bool is_calculated() const { return m_value.template has<NonnullRefPtr<CalculatedStyleValue>>(); }
T const& value() const
{
VERIFY(!is_calculated());
return m_value.template get<T>();
}
NonnullRefPtr<CalculatedStyleValue> const& calculated() const
{
VERIFY(is_calculated());
return m_value.template get<NonnullRefPtr<CalculatedStyleValue>>();
}
virtual T resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&) const = 0;
T resolved(Layout::Node const& layout_node) const
{
return m_value.visit(
[&](T const& t) {
return t;
},
[&](NonnullRefPtr<CalculatedStyleValue> const& calculated) {
return resolve_calculated(calculated, layout_node);
});
}
ErrorOr<String> to_string() const
{
if (is_calculated())
return m_value.template get<NonnullRefPtr<CalculatedStyleValue>>()->to_string();
return m_value.template get<T>().to_string();
}
bool operator==(CalculatedOr<T> const& other) const
{
if (is_calculated() || other.is_calculated())
return false;
return (m_value.template get<T>() == other.m_value.template get<T>());
}
private:
Variant<T, NonnullRefPtr<CalculatedStyleValue>> m_value;
};
class AngleOrCalculated : public CalculatedOr<Angle> {
public:
using CalculatedOr<Angle>::CalculatedOr;
Angle resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&) const override;
};
class FrequencyOrCalculated : public CalculatedOr<Frequency> {
public:
using CalculatedOr<Frequency>::CalculatedOr;
Frequency resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&) const override;
};
class LengthOrCalculated : public CalculatedOr<Length> {
public:
using CalculatedOr<Length>::CalculatedOr;
Length resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&) const override;
};
class PercentageOrCalculated : public CalculatedOr<Percentage> {
public:
using CalculatedOr<Percentage>::CalculatedOr;
Percentage resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&) const override;
};
class TimeOrCalculated : public CalculatedOr<Time> {
public:
using CalculatedOr<Time>::CalculatedOr;
Time resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&) const override;
};
}
template<>
struct AK::Formatter<Web::CSS::AngleOrCalculated> : Formatter<StringView> {
ErrorOr<void> format(FormatBuilder& builder, Web::CSS::AngleOrCalculated const& calculated_or)
{
return Formatter<StringView>::format(builder, TRY(calculated_or.to_string()));
}
};
template<>
struct AK::Formatter<Web::CSS::FrequencyOrCalculated> : Formatter<StringView> {
ErrorOr<void> format(FormatBuilder& builder, Web::CSS::FrequencyOrCalculated const& calculated_or)
{
return Formatter<StringView>::format(builder, TRY(calculated_or.to_string()));
}
};
template<>
struct AK::Formatter<Web::CSS::LengthOrCalculated> : Formatter<StringView> {
ErrorOr<void> format(FormatBuilder& builder, Web::CSS::LengthOrCalculated const& calculated_or)
{
return Formatter<StringView>::format(builder, TRY(calculated_or.to_string()));
}
};
template<>
struct AK::Formatter<Web::CSS::PercentageOrCalculated> : Formatter<StringView> {
ErrorOr<void> format(FormatBuilder& builder, Web::CSS::PercentageOrCalculated const& calculated_or)
{
return Formatter<StringView>::format(builder, TRY(calculated_or.to_string()));
}
};
template<>
struct AK::Formatter<Web::CSS::TimeOrCalculated> : Formatter<StringView> {
ErrorOr<void> format(FormatBuilder& builder, Web::CSS::TimeOrCalculated const& calculated_or)
{
return Formatter<StringView>::format(builder, TRY(calculated_or.to_string()));
}
};

View file

@ -83,8 +83,10 @@ public:
{
return m_value.visit(
[&](T const& t) {
if (t.is_calculated())
return calculated_style_value_contains_percentage(*t.calculated_style_value());
if constexpr (requires { t.is_calculated(); }) {
if (t.is_calculated())
return calculated_style_value_contains_percentage(*t.calculated_style_value());
}
return false;
},
[&](Percentage const&) {
@ -116,8 +118,11 @@ public:
{
return m_value.visit(
[&](T const& t) {
if (t.is_calculated())
return resolve_calculated(t.calculated_style_value(), layout_node, reference_value);
if constexpr (requires { t.is_calculated(); }) {
if (t.is_calculated())
return resolve_calculated(t.calculated_style_value(), layout_node, reference_value);
}
return t;
},
[&](Percentage const& percentage) {

View file

@ -28,6 +28,7 @@ namespace Web::CSS {
class AbstractImageStyleValue;
class Angle;
class AnglePercentage;
class AngleOrCalculated;
class AngleStyleValue;
class BackgroundRepeatStyleValue;
class BackgroundSizeStyleValue;
@ -61,6 +62,7 @@ class FontFace;
class FontStyleValue;
class Frequency;
class FrequencyPercentage;
class FrequencyOrCalculated;
class FrequencyStyleValue;
class GridAreaShorthandStyleValue;
class GridMinMax;
@ -79,6 +81,7 @@ class InitialStyleValue;
class Length;
class LengthBox;
class LengthPercentage;
class LengthOrCalculated;
class LengthStyleValue;
class LinearGradientStyleValue;
class ListStyleStyleValue;
@ -91,6 +94,7 @@ class Number;
class NumericStyleValue;
class OverflowStyleValue;
class Percentage;
class PercentageOrCalculated;
class PercentageStyleValue;
class PositionStyleValue;
class PropertyOwningCSSStyleDeclaration;
@ -113,6 +117,7 @@ class Supports;
class TextDecorationStyleValue;
class Time;
class TimePercentage;
class TimeOrCalculated;
class TimeStyleValue;
class TransformationStyleValue;
class UnicodeRange;