1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 16:47:45 +00:00

LibWeb: Implement Flex and FlexStyleValue types

This commit is contained in:
Sam Atkins 2023-09-28 15:18:14 +01:00 committed by Sam Atkins
parent f1d7ea67c0
commit b0317bb3a1
15 changed files with 258 additions and 6 deletions

View file

@ -38,6 +38,7 @@ static double resolve_value(CalculatedStyleValue::CalculationResult::Value value
return value.visit(
[](Number const& number) { return number.value(); },
[](Angle const& angle) { return angle.to_degrees(); },
[](Flex const& flex) { return flex.to_fr(); },
[](Frequency const& frequency) { return frequency.to_hertz(); },
[&context](Length const& length) { return length.to_px(*context).to_double(); },
[](Percentage const& percentage) { return percentage.value(); },
@ -74,6 +75,8 @@ static CalculatedStyleValue::CalculationResult to_resolved_type(CalculatedStyleV
return { Number(Number::Type::Number, value) };
case CalculatedStyleValue::ResolvedType::Angle:
return { Angle::make_degrees(value) };
case CalculatedStyleValue::ResolvedType::Flex:
return { Flex::make_fr(value) };
case CalculatedStyleValue::ResolvedType::Frequency:
return { Frequency::make_hertz(value) };
case CalculatedStyleValue::ResolvedType::Length:
@ -137,6 +140,7 @@ Optional<CalculatedStyleValue::ResolvedType> NumericCalculationNode::resolved_ty
return m_value.visit(
[](Number const&) { return CalculatedStyleValue::ResolvedType::Number; },
[](Angle const&) { return CalculatedStyleValue::ResolvedType::Angle; },
[](Flex const&) { return CalculatedStyleValue::ResolvedType::Flex; },
[](Frequency const&) { return CalculatedStyleValue::ResolvedType::Frequency; },
[](Length const&) { return CalculatedStyleValue::ResolvedType::Length; },
[](Percentage const&) { return CalculatedStyleValue::ResolvedType::Percentage; },
@ -175,7 +179,11 @@ Optional<CSSNumericType> NumericCalculationNode::determine_type(PropertyID prope
return CSSNumericType { CSSNumericType::BaseType::Frequency, 1 };
},
// FIXME: <resolution>
// FIXME: <flex>
[](Flex const&) {
// -> <flex>
// the type is «[ "flex" → 1 ]»
return CSSNumericType { CSSNumericType::BaseType::Flex, 1 };
},
// NOTE: <calc-constant> is a separate node type. (FIXME: Should it be?)
[property_id](Percentage const&) {
// -> <percentage>
@ -2053,6 +2061,24 @@ void CalculatedStyleValue::CalculationResult::add_or_subtract_internal(SumOperat
m_value = Angle::make_degrees(this_degrees - other_degrees);
}
},
[&](Flex const& flex) {
auto this_fr = flex.to_fr();
if (other.m_value.has<Flex>()) {
auto other_fr = other.m_value.get<Flex>().to_fr();
if (op == SumOperation::Add)
m_value = Flex::make_fr(this_fr + other_fr);
else
m_value = Flex::make_fr(this_fr - other_fr);
} else {
VERIFY(percentage_basis.has<Flex>());
auto other_fr = percentage_basis.get<Flex>().percentage_of(other.m_value.get<Percentage>()).to_fr();
if (op == SumOperation::Add)
m_value = Flex::make_fr(this_fr + other_fr);
else
m_value = Flex::make_fr(this_fr - other_fr);
}
},
[&](Frequency const& frequency) {
auto this_hertz = frequency.to_hertz();
if (other.m_value.has<Frequency>()) {
@ -2151,6 +2177,9 @@ void CalculatedStyleValue::CalculationResult::multiply_by(CalculationResult cons
[&](Angle const& angle) {
m_value = Angle::make_degrees(angle.to_degrees() * other.m_value.get<Number>().value());
},
[&](Flex const& flex) {
m_value = Flex::make_fr(flex.to_fr() * other.m_value.get<Number>().value());
},
[&](Frequency const& frequency) {
m_value = Frequency::make_hertz(frequency.to_hertz() * other.m_value.get<Number>().value());
},
@ -2183,6 +2212,9 @@ void CalculatedStyleValue::CalculationResult::divide_by(CalculationResult const&
[&](Angle const& angle) {
m_value = Angle::make_degrees(angle.to_degrees() / denominator);
},
[&](Flex const& flex) {
m_value = Flex::make_fr(flex.to_fr() / denominator);
},
[&](Frequency const& frequency) {
m_value = Frequency::make_hertz(frequency.to_hertz() / denominator);
},
@ -2206,6 +2238,9 @@ void CalculatedStyleValue::CalculationResult::negate()
[&](Angle const& angle) {
m_value = Angle { 0 - angle.raw_value(), angle.type() };
},
[&](Flex const& flex) {
m_value = Flex { 0 - flex.raw_value(), flex.type() };
},
[&](Frequency const& frequency) {
m_value = Frequency { 0 - frequency.raw_value(), frequency.type() };
},
@ -2230,6 +2265,9 @@ void CalculatedStyleValue::CalculationResult::invert()
[&](Angle const& angle) {
m_value = Angle { 1 / angle.raw_value(), angle.type() };
},
[&](Flex const& flex) {
m_value = Flex { 1 / flex.raw_value(), flex.type() };
},
[&](Frequency const& frequency) {
m_value = Frequency { 1 / frequency.raw_value(), frequency.type() };
},
@ -2283,6 +2321,15 @@ Optional<Angle> CalculatedStyleValue::resolve_angle_percentage(Angle const& perc
});
}
Optional<Flex> CalculatedStyleValue::resolve_flex() const
{
auto result = m_calculation->resolve({}, {});
if (result.value().has<Flex>())
return result.value().get<Flex>();
return {};
}
Optional<Frequency> CalculatedStyleValue::resolve_frequency() const
{
auto result = m_calculation->resolve({}, {});

View file

@ -12,6 +12,7 @@
#include <AK/Function.h>
#include <LibWeb/CSS/Angle.h>
#include <LibWeb/CSS/CSSNumericType.h>
#include <LibWeb/CSS/Flex.h>
#include <LibWeb/CSS/Frequency.h>
#include <LibWeb/CSS/Length.h>
#include <LibWeb/CSS/Percentage.h>
@ -26,6 +27,7 @@ class CalculatedStyleValue : public StyleValue {
public:
enum class ResolvedType {
Angle,
Flex,
Frequency,
Integer,
Length,
@ -43,11 +45,11 @@ public:
Divide,
};
using PercentageBasis = Variant<Empty, Angle, Frequency, Length, Time>;
using PercentageBasis = Variant<Empty, Angle, Flex, Frequency, Length, Time>;
class CalculationResult {
public:
using Value = Variant<Number, Angle, Frequency, Length, Percentage, Time>;
using Value = Variant<Number, Angle, Flex, Frequency, Length, Percentage, Time>;
CalculationResult(Value value)
: m_value(move(value))
{
@ -79,6 +81,9 @@ public:
Optional<Angle> resolve_angle() const;
Optional<Angle> resolve_angle_percentage(Angle const& percentage_basis) const;
bool resolves_to_flex() const { return m_resolved_type.matches_flex(); }
Optional<Flex> resolve_flex() const;
bool resolves_to_frequency() const { return m_resolved_type.matches_frequency(); }
bool resolves_to_frequency_percentage() const { return m_resolved_type.matches_frequency_percentage(); }
Optional<Frequency> resolve_frequency() const;

View file

@ -0,0 +1,39 @@
/*
* Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/CSS/Flex.h>
#include <LibWeb/CSS/StyleValue.h>
namespace Web::CSS {
class FlexStyleValue final : public StyleValueWithDefaultOperators<FlexStyleValue> {
public:
static ValueComparingNonnullRefPtr<FlexStyleValue> create(Flex flex)
{
return adopt_ref(*new (nothrow) FlexStyleValue(move(flex)));
}
virtual ~FlexStyleValue() override = default;
Flex const& flex() const { return m_flex; }
Flex& flex() { return m_flex; }
virtual String to_string() const override { return m_flex.to_string(); }
bool properties_equal(FlexStyleValue const& other) const { return m_flex == other.m_flex; }
private:
FlexStyleValue(Flex&& flex)
: StyleValueWithDefaultOperators(Type::Flex)
, m_flex(flex)
{
}
Flex m_flex;
};
}