mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-10-24 08:59:50 +00:00
LibWeb: Set up initial infrastructure for non-math functions in calc
There are some non-math functions (such as tree counting functions) which we should allow within `calc()`s . This commit implements the initial infrastructure for this. We don't yet parse any of these non-math functions in `parse_a_calculation` so there is no functional change.
This commit is contained in:
parent
831e471444
commit
55bcdcf824
Notes:
github-actions[bot]
2025-10-20 15:13:37 +00:00
Author: https://github.com/Calme1709
Commit: 55bcdcf824
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6426
Reviewed-by: https://github.com/AtkinsSJ ✅
5 changed files with 89 additions and 9 deletions
|
|
@ -14,8 +14,6 @@
|
|||
|
||||
namespace Web::CSS {
|
||||
|
||||
struct CalculationContext;
|
||||
|
||||
enum class AllowDiscrete {
|
||||
Yes,
|
||||
No,
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#include <AK/StringConversions.h>
|
||||
#include <AK/TemporaryChange.h>
|
||||
#include <LibWeb/CSS/FontFace.h>
|
||||
#include <LibWeb/CSS/MathFunctions.h>
|
||||
#include <LibWeb/CSS/Parser/ArbitrarySubstitutionFunctions.h>
|
||||
#include <LibWeb/CSS/Parser/ErrorReporter.h>
|
||||
#include <LibWeb/CSS/Parser/Parser.h>
|
||||
|
|
@ -4249,8 +4250,7 @@ RefPtr<CalculationNode const> Parser::convert_to_calculation_node(CalcParsing::N
|
|||
}
|
||||
|
||||
// 2. If leaf is a math function, replace leaf with the internal representation of that math function.
|
||||
// NOTE: All function tokens at this point should be math functions.
|
||||
if (component_value->is_function()) {
|
||||
if (component_value->is_function() && math_function_from_string(component_value->function().name).has_value()) {
|
||||
auto const& function = component_value->function();
|
||||
auto leaf_calculation = parse_a_calc_function_node(function, context);
|
||||
if (!leaf_calculation)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright (c) 2025, Callum Law <callumlaw1709@outlook.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibWeb/CSS/StyleValues/StyleValue.h>
|
||||
|
||||
namespace Web::CSS {
|
||||
|
||||
class AbstractNonMathCalcFunctionStyleValue : public StyleValue {
|
||||
using StyleValue::StyleValue;
|
||||
|
||||
public:
|
||||
virtual RefPtr<CalculationNode const> resolve_to_calculation_node(CalculationContext const&, CalculationResolutionContext const&) const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -23,6 +23,7 @@
|
|||
#include <LibWeb/CSS/Percentage.h>
|
||||
#include <LibWeb/CSS/PropertyID.h>
|
||||
#include <LibWeb/CSS/PropertyNameAndID.h>
|
||||
#include <LibWeb/CSS/StyleValues/AbstractNonMathCalcFunctionStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/AngleStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/FlexStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/FrequencyStyleValue.h>
|
||||
|
|
@ -411,10 +412,12 @@ static String serialize_a_calculation_tree(CalculationNode const& root, Calculat
|
|||
// NOTE: Already the case.
|
||||
|
||||
// 2. If root is a numeric value, or a non-math function, serialize root per the normal rules for it and return the result.
|
||||
// FIXME: Support non-math functions in calculation trees.
|
||||
if (root.type() == CalculationNode::Type::Numeric)
|
||||
return static_cast<NumericCalculationNode const&>(root).value_to_string();
|
||||
|
||||
if (root.type() == CalculationNode::Type::NonMathFunction)
|
||||
return as<NonMathFunctionCalculationNode>(root).function()->to_string(serialization_mode);
|
||||
|
||||
// 3. If root is anything but a Sum, Negate, Product, or Invert node, serialize a math function for the function
|
||||
// corresponding to the node type, treating the node’s children as the function’s comma-separated calculation
|
||||
// arguments, and return the result.
|
||||
|
|
@ -580,6 +583,7 @@ StringView CalculationNode::name() const
|
|||
case Type::Product:
|
||||
case Type::Negate:
|
||||
case Type::Invert:
|
||||
case Type::NonMathFunction:
|
||||
return "calc"sv;
|
||||
}
|
||||
VERIFY_NOT_REACHED();
|
||||
|
|
@ -2473,6 +2477,35 @@ bool RemCalculationNode::equals(CalculationNode const& other) const
|
|||
&& m_y->equals(*static_cast<RemCalculationNode const&>(other).m_y);
|
||||
}
|
||||
|
||||
NonnullRefPtr<NonMathFunctionCalculationNode const> NonMathFunctionCalculationNode::create(AbstractNonMathCalcFunctionStyleValue const& function, NumericType numeric_type)
|
||||
{
|
||||
return adopt_ref(*new (nothrow) NonMathFunctionCalculationNode(move(function), move(numeric_type)));
|
||||
}
|
||||
|
||||
NonMathFunctionCalculationNode::NonMathFunctionCalculationNode(AbstractNonMathCalcFunctionStyleValue const& function, NumericType numeric_type)
|
||||
: CalculationNode(Type::NonMathFunction, numeric_type)
|
||||
, m_function(function)
|
||||
{
|
||||
}
|
||||
|
||||
NonMathFunctionCalculationNode::~NonMathFunctionCalculationNode() = default;
|
||||
|
||||
void NonMathFunctionCalculationNode::dump(StringBuilder& builder, int indent) const
|
||||
{
|
||||
builder.appendff("{: >{}}NON-MATH FUNCTION: {}", "", indent, m_function->to_string(SerializationMode::Normal));
|
||||
}
|
||||
|
||||
bool NonMathFunctionCalculationNode::equals(CalculationNode const& other) const
|
||||
{
|
||||
if (this == &other)
|
||||
return true;
|
||||
|
||||
if (type() != other.type())
|
||||
return false;
|
||||
|
||||
return static_cast<NonMathFunctionCalculationNode const&>(other).function() == m_function;
|
||||
}
|
||||
|
||||
CalculatedStyleValue::CalculationResult CalculatedStyleValue::CalculationResult::from_value(Value const& value, CalculationResolutionContext const& context, Optional<NumericType> numeric_type)
|
||||
{
|
||||
auto number = value.visit(
|
||||
|
|
@ -2931,7 +2964,15 @@ NonnullRefPtr<CalculationNode const> simplify_a_calculation_tree(CalculationNode
|
|||
}
|
||||
|
||||
// 2. If root is any other leaf node (not an operator node):
|
||||
// FIXME: We don't yet allow any of these inside a calculation tree. Revisit once we do.
|
||||
if (root->type() == CalculationNode::Type::NonMathFunction) {
|
||||
// 1. If there is enough information available to determine its numeric value, return its value, expressed in
|
||||
// the value’s canonical unit.
|
||||
if (auto resolved_calculation_node = as<NonMathFunctionCalculationNode>(*root).function()->resolve_to_calculation_node(context, resolution_context))
|
||||
return resolved_calculation_node.release_nonnull();
|
||||
|
||||
// 2. Otherwise, return root.
|
||||
return root;
|
||||
}
|
||||
|
||||
// 3. At this point, root is an operator node. Simplify all the calculation children of root.
|
||||
root = root->with_simplified_children(context, resolution_context);
|
||||
|
|
|
|||
|
|
@ -19,13 +19,12 @@
|
|||
#include <LibWeb/CSS/NumericType.h>
|
||||
#include <LibWeb/CSS/Percentage.h>
|
||||
#include <LibWeb/CSS/Resolution.h>
|
||||
#include <LibWeb/CSS/StyleValues/AbstractNonMathCalcFunctionStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/StyleValue.h>
|
||||
#include <LibWeb/CSS/Time.h>
|
||||
|
||||
namespace Web::CSS {
|
||||
|
||||
class CalculationNode;
|
||||
|
||||
// https://drafts.csswg.org/css-values-4/#calc-context
|
||||
// Contains the context available at parse-time.
|
||||
struct CalculationContext {
|
||||
|
|
@ -146,7 +145,7 @@ public:
|
|||
enum class Type {
|
||||
Numeric,
|
||||
// NOTE: Currently, any value with a `var()` or `attr()` function in it is always an
|
||||
// UnresolvedStyleValue so we do not have to implement a NonMathFunction type here.
|
||||
// UnresolvedStyleValue so we do not have to implement them as CalculationNodes.
|
||||
|
||||
// Comparison function nodes, a sub-type of operator node
|
||||
// https://drafts.csswg.org/css-values-4/#comp-func
|
||||
|
|
@ -189,6 +188,9 @@ public:
|
|||
Round,
|
||||
Mod,
|
||||
Rem,
|
||||
|
||||
// Non-math functions
|
||||
NonMathFunction
|
||||
};
|
||||
using NumericValue = CalculatedStyleValue::CalculationResult::Value;
|
||||
|
||||
|
|
@ -764,6 +766,25 @@ private:
|
|||
NonnullRefPtr<CalculationNode const> m_y;
|
||||
};
|
||||
|
||||
class NonMathFunctionCalculationNode final : public CalculationNode {
|
||||
public:
|
||||
static NonnullRefPtr<NonMathFunctionCalculationNode const> create(AbstractNonMathCalcFunctionStyleValue const&, NumericType);
|
||||
~NonMathFunctionCalculationNode();
|
||||
|
||||
virtual bool contains_percentage() const override { return false; }
|
||||
virtual NonnullRefPtr<CalculationNode const> with_simplified_children(CalculationContext const&, CalculationResolutionContext const&) const override { return *this; }
|
||||
virtual Vector<NonnullRefPtr<CalculationNode const>> children() const override { return {}; }
|
||||
|
||||
virtual void dump(StringBuilder&, int indent) const override;
|
||||
virtual bool equals(CalculationNode const&) const override;
|
||||
|
||||
ValueComparingNonnullRefPtr<AbstractNonMathCalcFunctionStyleValue const> function() const { return m_function; }
|
||||
|
||||
private:
|
||||
NonMathFunctionCalculationNode(AbstractNonMathCalcFunctionStyleValue const& function, NumericType);
|
||||
ValueComparingNonnullRefPtr<AbstractNonMathCalcFunctionStyleValue const> m_function;
|
||||
};
|
||||
|
||||
// https://drafts.csswg.org/css-values-4/#calc-simplification
|
||||
NonnullRefPtr<CalculationNode const> simplify_a_calculation_tree(CalculationNode const& root, CalculationContext const& context, CalculationResolutionContext const& resolution_context);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue