ladybird/Libraries/LibWeb/CSS/CSSMathValue.cpp
Sam Atkins 078bc1a471 LibWeb/CSS: Allow converting CSSMathValues to StyleValues
Because we store calculations as a tree of CalculationNodes inside a
CalculatedStyleValue, instead of a tree of StyleValues directly, this
implements a create_calculation_node() method on CSSNumericValue.
CSSMathValue::create_an_internal_representation() then calls
create_calculation_node() on itself, and wraps it in a
CalculatedStyleValue.

Lots of WPT passes again! Some regressions, which are expected: `cursor`
fails a test for the same reason it fails other that set it to some
kind of numeric value: We don't distinguish between "can contain a
number" and "can accept a number by itself". This will affect any
similar properties, but overall this is a big improvement.
2025-10-13 09:59:38 +01:00

68 lines
2.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) 2025, Sam Atkins <sam@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "CSSMathValue.h"
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/CSS/PropertyNameAndID.h>
#include <LibWeb/CSS/StyleValues/CalculatedStyleValue.h>
namespace Web::CSS {
GC_DEFINE_ALLOCATOR(CSSMathValue);
CSSMathValue::CSSMathValue(JS::Realm& realm, Bindings::CSSMathOperator operator_, NumericType type)
: CSSNumericValue(realm, move(type))
, m_operator(operator_)
{
}
void CSSMathValue::initialize(JS::Realm& realm)
{
WEB_SET_PROTOTYPE_FOR_INTERFACE(CSSMathValue);
Base::initialize(realm);
}
// https://drafts.css-houdini.org/css-typed-om-1/#create-an-internal-representation
WebIDL::ExceptionOr<NonnullRefPtr<StyleValue const>> CSSMathValue::create_an_internal_representation(PropertyNameAndID const& property) const
{
// If value is a CSSStyleValue subclass,
// If value does not match the grammar of a list-valued property iteration of property, throw a TypeError.
//
// If any component of propertys CSS grammar has a limited numeric range, and the corresponding part of value
// is a CSSUnitValue that is outside of that range, replace that value with the result of wrapping it in a
// fresh CSSMathSum whose values internal slot contains only that part of value.
//
// Return the value.
// FIXME: Check types allowed by registered custom properties.
auto context = CalculationContext::for_property(property);
auto matches = [&] {
if (type().matches_angle(context.percentages_resolve_as))
return property_accepts_type(property.id(), ValueType::Angle);
if (type().matches_flex(context.percentages_resolve_as))
return property_accepts_type(property.id(), ValueType::Flex);
if (type().matches_frequency(context.percentages_resolve_as))
return property_accepts_type(property.id(), ValueType::Frequency);
if (type().matches_length(context.percentages_resolve_as))
return property_accepts_type(property.id(), ValueType::Length);
if (type().matches_number(context.percentages_resolve_as))
return property_accepts_type(property.id(), ValueType::Number);
if (type().matches_percentage())
return property_accepts_type(property.id(), ValueType::Percentage);
if (type().matches_resolution(context.percentages_resolve_as))
return property_accepts_type(property.id(), ValueType::Resolution);
if (type().matches_time(context.percentages_resolve_as))
return property_accepts_type(property.id(), ValueType::Time);
return false;
}();
if (!matches)
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Property does not accept values of this type."sv };
return CalculatedStyleValue::create(TRY(create_calculation_node(context)), type(), move(context));
}
}