mirror of
https://github.com/RGBCube/serenity
synced 2025-07-23 19:37:34 +00:00
LibWeb: Resolve type of calc() expressions at parse-time
See https://www.w3.org/TR/css-values-3/#calc-type-checking If the sub-expressions' types are incompatible, we discard the calc() as invalid. Had to do some minor rearranging/renaming of the Calc structs to make the `resolve_foo_type()` templates work too.
This commit is contained in:
parent
b818d952d1
commit
b69f6097de
4 changed files with 265 additions and 25 deletions
|
@ -2091,17 +2091,52 @@ RefPtr<StyleValue> Parser::parse_builtin_value(StyleComponentValueRule const& co
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RefPtr<StyleValue> Parser::parse_calculated_value(Vector<StyleComponentValueRule> const& component_values)
|
||||||
|
{
|
||||||
|
auto calc_expression = parse_calc_expression(component_values);
|
||||||
|
if (calc_expression == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
auto calc_type = calc_expression->resolved_type();
|
||||||
|
if (!calc_type.has_value()) {
|
||||||
|
dbgln("calc() resolved as invalid!!!");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] auto to_string = [](CalculatedStyleValue::ResolvedType type) {
|
||||||
|
switch (type) {
|
||||||
|
case CalculatedStyleValue::ResolvedType::Angle:
|
||||||
|
return "Angle"sv;
|
||||||
|
case CalculatedStyleValue::ResolvedType::Frequency:
|
||||||
|
return "Frequency"sv;
|
||||||
|
case CalculatedStyleValue::ResolvedType::Integer:
|
||||||
|
return "Integer"sv;
|
||||||
|
case CalculatedStyleValue::ResolvedType::Length:
|
||||||
|
return "Length"sv;
|
||||||
|
case CalculatedStyleValue::ResolvedType::Number:
|
||||||
|
return "Number"sv;
|
||||||
|
case CalculatedStyleValue::ResolvedType::Percentage:
|
||||||
|
return "Percentage"sv;
|
||||||
|
case CalculatedStyleValue::ResolvedType::Time:
|
||||||
|
return "Time"sv;
|
||||||
|
}
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
};
|
||||||
|
dbgln_if(CSS_PARSER_DEBUG, "Deduced calc() resolved type as: {}", to_string(calc_type.value()));
|
||||||
|
|
||||||
|
// FIXME: Either produce a string value of calc() here, or do so in CalculatedStyleValue::to_string().
|
||||||
|
return CalculatedStyleValue::create("(FIXME:calc to string)", calc_expression.release_nonnull(), calc_type.release_value());
|
||||||
|
}
|
||||||
|
|
||||||
RefPtr<StyleValue> Parser::parse_dynamic_value(StyleComponentValueRule const& component_value)
|
RefPtr<StyleValue> Parser::parse_dynamic_value(StyleComponentValueRule const& component_value)
|
||||||
{
|
{
|
||||||
if (component_value.is_function()) {
|
if (component_value.is_function()) {
|
||||||
auto& function = component_value.function();
|
auto& function = component_value.function();
|
||||||
|
|
||||||
if (function.name().equals_ignoring_case("calc")) {
|
if (function.name().equals_ignoring_case("calc"))
|
||||||
auto calc_expression = parse_calc_expression(function.values());
|
return parse_calculated_value(function.values());
|
||||||
// FIXME: Either produce a string value of calc() here, or do so in CalculatedStyleValue::to_string().
|
|
||||||
if (calc_expression)
|
if (function.name().equals_ignoring_case("var")) {
|
||||||
return CalculatedStyleValue::create("(FIXME:calc to string)", calc_expression.release_nonnull());
|
|
||||||
} else if (function.name().equals_ignoring_case("var")) {
|
|
||||||
// Declarations using `var()` should already be parsed as an UnresolvedStyleValue before this point.
|
// Declarations using `var()` should already be parsed as an UnresolvedStyleValue before this point.
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
@ -4189,7 +4224,7 @@ OwnPtr<CalculatedStyleValue::CalcProductPartWithOperator> Parser::parse_calc_pro
|
||||||
// Note: The default value is not used or passed around.
|
// Note: The default value is not used or passed around.
|
||||||
auto product_with_operator = make<CalculatedStyleValue::CalcProductPartWithOperator>(
|
auto product_with_operator = make<CalculatedStyleValue::CalcProductPartWithOperator>(
|
||||||
CalculatedStyleValue::ProductOperation::Multiply,
|
CalculatedStyleValue::ProductOperation::Multiply,
|
||||||
CalculatedStyleValue::CalcNumberValue(0));
|
CalculatedStyleValue::CalcNumberValue { 0 });
|
||||||
|
|
||||||
tokens.skip_whitespace();
|
tokens.skip_whitespace();
|
||||||
|
|
||||||
|
@ -4227,7 +4262,7 @@ OwnPtr<CalculatedStyleValue::CalcNumberProductPartWithOperator> Parser::parse_ca
|
||||||
// Note: The default value is not used or passed around.
|
// Note: The default value is not used or passed around.
|
||||||
auto number_product_with_operator = make<CalculatedStyleValue::CalcNumberProductPartWithOperator>(
|
auto number_product_with_operator = make<CalculatedStyleValue::CalcNumberProductPartWithOperator>(
|
||||||
CalculatedStyleValue::ProductOperation::Multiply,
|
CalculatedStyleValue::ProductOperation::Multiply,
|
||||||
CalculatedStyleValue::CalcNumberValue(0));
|
CalculatedStyleValue::CalcNumberValue { 0 });
|
||||||
|
|
||||||
tokens.skip_whitespace();
|
tokens.skip_whitespace();
|
||||||
|
|
||||||
|
@ -4259,7 +4294,7 @@ OwnPtr<CalculatedStyleValue::CalcNumberProductPartWithOperator> Parser::parse_ca
|
||||||
OwnPtr<CalculatedStyleValue::CalcNumberProduct> Parser::parse_calc_number_product(TokenStream<StyleComponentValueRule>& tokens)
|
OwnPtr<CalculatedStyleValue::CalcNumberProduct> Parser::parse_calc_number_product(TokenStream<StyleComponentValueRule>& tokens)
|
||||||
{
|
{
|
||||||
auto calc_number_product = make<CalculatedStyleValue::CalcNumberProduct>(
|
auto calc_number_product = make<CalculatedStyleValue::CalcNumberProduct>(
|
||||||
CalculatedStyleValue::CalcNumberValue(0),
|
CalculatedStyleValue::CalcNumberValue { 0 },
|
||||||
NonnullOwnPtrVector<CalculatedStyleValue::CalcNumberProductPartWithOperator> {});
|
NonnullOwnPtrVector<CalculatedStyleValue::CalcNumberProductPartWithOperator> {});
|
||||||
|
|
||||||
auto first_calc_number_value_or_error = parse_calc_number_value(tokens);
|
auto first_calc_number_value_or_error = parse_calc_number_value(tokens);
|
||||||
|
@ -4330,20 +4365,20 @@ Optional<CalculatedStyleValue::CalcNumberValue> Parser::parse_calc_number_value(
|
||||||
auto block_values = TokenStream(first.block().values());
|
auto block_values = TokenStream(first.block().values());
|
||||||
auto calc_number_sum = parse_calc_number_sum(block_values);
|
auto calc_number_sum = parse_calc_number_sum(block_values);
|
||||||
if (calc_number_sum)
|
if (calc_number_sum)
|
||||||
return { calc_number_sum.release_nonnull() };
|
return CalculatedStyleValue::CalcNumberValue { calc_number_sum.release_nonnull() };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!first.is(Token::Type::Number))
|
if (!first.is(Token::Type::Number))
|
||||||
return {};
|
return {};
|
||||||
tokens.next_token();
|
tokens.next_token();
|
||||||
|
|
||||||
return first.token().number_value();
|
return CalculatedStyleValue::CalcNumberValue { static_cast<float>(first.token().number_value()) };
|
||||||
}
|
}
|
||||||
|
|
||||||
OwnPtr<CalculatedStyleValue::CalcProduct> Parser::parse_calc_product(TokenStream<StyleComponentValueRule>& tokens)
|
OwnPtr<CalculatedStyleValue::CalcProduct> Parser::parse_calc_product(TokenStream<StyleComponentValueRule>& tokens)
|
||||||
{
|
{
|
||||||
auto calc_product = make<CalculatedStyleValue::CalcProduct>(
|
auto calc_product = make<CalculatedStyleValue::CalcProduct>(
|
||||||
CalculatedStyleValue::CalcValue(0),
|
CalculatedStyleValue::CalcValue { 0 },
|
||||||
NonnullOwnPtrVector<CalculatedStyleValue::CalcProductPartWithOperator> {});
|
NonnullOwnPtrVector<CalculatedStyleValue::CalcProductPartWithOperator> {});
|
||||||
|
|
||||||
auto first_calc_value_or_error = parse_calc_value(tokens);
|
auto first_calc_value_or_error = parse_calc_value(tokens);
|
||||||
|
|
|
@ -213,6 +213,7 @@ private:
|
||||||
RefPtr<StyleValue> parse_css_value(StyleComponentValueRule const&);
|
RefPtr<StyleValue> parse_css_value(StyleComponentValueRule const&);
|
||||||
RefPtr<StyleValue> parse_builtin_value(StyleComponentValueRule const&);
|
RefPtr<StyleValue> parse_builtin_value(StyleComponentValueRule const&);
|
||||||
RefPtr<StyleValue> parse_dynamic_value(StyleComponentValueRule const&);
|
RefPtr<StyleValue> parse_dynamic_value(StyleComponentValueRule const&);
|
||||||
|
RefPtr<StyleValue> parse_calculated_value(Vector<StyleComponentValueRule> const&);
|
||||||
RefPtr<StyleValue> parse_dimension_value(StyleComponentValueRule const&);
|
RefPtr<StyleValue> parse_dimension_value(StyleComponentValueRule const&);
|
||||||
RefPtr<StyleValue> parse_numeric_value(StyleComponentValueRule const&);
|
RefPtr<StyleValue> parse_numeric_value(StyleComponentValueRule const&);
|
||||||
RefPtr<StyleValue> parse_identifier_value(StyleComponentValueRule const&);
|
RefPtr<StyleValue> parse_identifier_value(StyleComponentValueRule const&);
|
||||||
|
|
|
@ -289,7 +289,7 @@ Optional<Length> CalculatedStyleValue::resolve_length(Layout::Node const& layout
|
||||||
|
|
||||||
static float resolve_calc_value(CalculatedStyleValue::CalcValue const& calc_value, Layout::Node const& layout_node)
|
static float resolve_calc_value(CalculatedStyleValue::CalcValue const& calc_value, Layout::Node const& layout_node)
|
||||||
{
|
{
|
||||||
return calc_value.visit(
|
return calc_value.value.visit(
|
||||||
[](float value) { return value; },
|
[](float value) { return value; },
|
||||||
[&](Length const& length) {
|
[&](Length const& length) {
|
||||||
return length.resolved_or_zero(layout_node).to_px(layout_node);
|
return length.resolved_or_zero(layout_node).to_px(layout_node);
|
||||||
|
@ -325,7 +325,7 @@ static float resolve_calc_number_sum(NonnullOwnPtr<CalculatedStyleValue::CalcNum
|
||||||
auto value = resolve_calc_number_product(calc_number_sum->first_calc_number_product);
|
auto value = resolve_calc_number_product(calc_number_sum->first_calc_number_product);
|
||||||
|
|
||||||
for (auto& additional_product : calc_number_sum->zero_or_more_additional_calc_number_products) {
|
for (auto& additional_product : calc_number_sum->zero_or_more_additional_calc_number_products) {
|
||||||
auto additional_value = resolve_calc_number_product(additional_product.calc_number_product);
|
auto additional_value = resolve_calc_number_product(additional_product.value);
|
||||||
if (additional_product.op == CSS::CalculatedStyleValue::SumOperation::Add)
|
if (additional_product.op == CSS::CalculatedStyleValue::SumOperation::Add)
|
||||||
value += additional_value;
|
value += additional_value;
|
||||||
else if (additional_product.op == CSS::CalculatedStyleValue::SumOperation::Subtract)
|
else if (additional_product.op == CSS::CalculatedStyleValue::SumOperation::Subtract)
|
||||||
|
@ -339,7 +339,7 @@ static float resolve_calc_number_sum(NonnullOwnPtr<CalculatedStyleValue::CalcNum
|
||||||
|
|
||||||
static float resolve_calc_number_value(CalculatedStyleValue::CalcNumberValue const& number_value)
|
static float resolve_calc_number_value(CalculatedStyleValue::CalcNumberValue const& number_value)
|
||||||
{
|
{
|
||||||
return number_value.visit(
|
return number_value.value.visit(
|
||||||
[](float number) { return number; },
|
[](float number) { return number; },
|
||||||
[](NonnullOwnPtr<CalculatedStyleValue::CalcNumberSum> const& calc_number_sum) {
|
[](NonnullOwnPtr<CalculatedStyleValue::CalcNumberSum> const& calc_number_sum) {
|
||||||
return resolve_calc_number_sum(calc_number_sum);
|
return resolve_calc_number_sum(calc_number_sum);
|
||||||
|
@ -374,7 +374,7 @@ static float resolve_calc_sum(NonnullOwnPtr<CalculatedStyleValue::CalcSum> const
|
||||||
auto value = resolve_calc_product(calc_sum->first_calc_product, layout_node);
|
auto value = resolve_calc_product(calc_sum->first_calc_product, layout_node);
|
||||||
|
|
||||||
for (auto& additional_product : calc_sum->zero_or_more_additional_calc_products) {
|
for (auto& additional_product : calc_sum->zero_or_more_additional_calc_products) {
|
||||||
auto additional_value = resolve_calc_product(additional_product.calc_product, layout_node);
|
auto additional_value = resolve_calc_product(additional_product.value, layout_node);
|
||||||
if (additional_product.op == CalculatedStyleValue::SumOperation::Add)
|
if (additional_product.op == CalculatedStyleValue::SumOperation::Add)
|
||||||
value += additional_value;
|
value += additional_value;
|
||||||
else if (additional_product.op == CalculatedStyleValue::SumOperation::Subtract)
|
else if (additional_product.op == CalculatedStyleValue::SumOperation::Subtract)
|
||||||
|
@ -386,6 +386,174 @@ static float resolve_calc_sum(NonnullOwnPtr<CalculatedStyleValue::CalcSum> const
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool is_number(CalculatedStyleValue::ResolvedType type)
|
||||||
|
{
|
||||||
|
return type == CalculatedStyleValue::ResolvedType::Number || type == CalculatedStyleValue::ResolvedType::Integer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_dimension(CalculatedStyleValue::ResolvedType type)
|
||||||
|
{
|
||||||
|
return type != CalculatedStyleValue::ResolvedType::Number
|
||||||
|
&& type != CalculatedStyleValue::ResolvedType::Integer
|
||||||
|
&& type != CalculatedStyleValue::ResolvedType::Percentage;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename SumWithOperator>
|
||||||
|
static Optional<CalculatedStyleValue::ResolvedType> resolve_sum_type(CalculatedStyleValue::ResolvedType first_type, NonnullOwnPtrVector<SumWithOperator> const& zero_or_more_additional_products)
|
||||||
|
{
|
||||||
|
auto type = first_type;
|
||||||
|
|
||||||
|
for (auto const& product : zero_or_more_additional_products) {
|
||||||
|
auto maybe_product_type = product.resolved_type();
|
||||||
|
if (!maybe_product_type.has_value())
|
||||||
|
return {};
|
||||||
|
auto product_type = maybe_product_type.value();
|
||||||
|
|
||||||
|
// At + or -, check that both sides have the same type, or that one side is a <number> and the other is an <integer>.
|
||||||
|
// If both sides are the same type, resolve to that type.
|
||||||
|
if (product_type == type)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// If one side is a <number> and the other is an <integer>, resolve to <number>.
|
||||||
|
if (is_number(type) && is_number(product_type)) {
|
||||||
|
type = CalculatedStyleValue::ResolvedType::Number;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: calc() handles <percentage> by allowing them to pretend to be whatever <dimension> type is allowed at this location.
|
||||||
|
// Since we can't easily check what that type is, we just allow <percentage> to combine with any other <dimension> type.
|
||||||
|
if (type == CalculatedStyleValue::ResolvedType::Percentage && is_dimension(product_type)) {
|
||||||
|
type = product_type;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (is_dimension(type) && product_type == CalculatedStyleValue::ResolvedType::Percentage)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<CalculatedStyleValue::ResolvedType> CalculatedStyleValue::CalcSum::resolved_type() const
|
||||||
|
{
|
||||||
|
auto maybe_type = first_calc_product->resolved_type();
|
||||||
|
if (!maybe_type.has_value())
|
||||||
|
return {};
|
||||||
|
auto type = maybe_type.value();
|
||||||
|
return resolve_sum_type(type, zero_or_more_additional_calc_products);
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<CalculatedStyleValue::ResolvedType> CalculatedStyleValue::CalcNumberSum::resolved_type() const
|
||||||
|
{
|
||||||
|
auto maybe_type = first_calc_number_product->resolved_type();
|
||||||
|
if (!maybe_type.has_value())
|
||||||
|
return {};
|
||||||
|
auto type = maybe_type.value();
|
||||||
|
return resolve_sum_type(type, zero_or_more_additional_calc_number_products);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ProductWithOperator>
|
||||||
|
static Optional<CalculatedStyleValue::ResolvedType> resolve_product_type(CalculatedStyleValue::ResolvedType first_type, NonnullOwnPtrVector<ProductWithOperator> const& zero_or_more_additional_values)
|
||||||
|
{
|
||||||
|
auto type = first_type;
|
||||||
|
|
||||||
|
for (auto const& value : zero_or_more_additional_values) {
|
||||||
|
auto maybe_value_type = value.resolved_type();
|
||||||
|
if (!maybe_value_type.has_value())
|
||||||
|
return {};
|
||||||
|
auto value_type = maybe_value_type.value();
|
||||||
|
|
||||||
|
if (value.op == CalculatedStyleValue::ProductOperation::Multiply) {
|
||||||
|
// At *, check that at least one side is <number>.
|
||||||
|
if (!(is_number(type) || is_number(value_type)))
|
||||||
|
return {};
|
||||||
|
// If both sides are <integer>, resolve to <integer>.
|
||||||
|
if (type == CalculatedStyleValue::ResolvedType::Integer && value_type == CalculatedStyleValue::ResolvedType::Integer) {
|
||||||
|
type = CalculatedStyleValue::ResolvedType::Integer;
|
||||||
|
} else {
|
||||||
|
// Otherwise, resolve to the type of the other side.
|
||||||
|
if (is_number(type))
|
||||||
|
type = value_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
VERIFY(value.op == CalculatedStyleValue::ProductOperation::Divide);
|
||||||
|
// At /, check that the right side is <number>.
|
||||||
|
if (!is_number(value_type))
|
||||||
|
return {};
|
||||||
|
// If the left side is <integer>, resolve to <number>.
|
||||||
|
if (type == CalculatedStyleValue::ResolvedType::Integer) {
|
||||||
|
type = CalculatedStyleValue::ResolvedType::Number;
|
||||||
|
} else {
|
||||||
|
// Otherwise, resolve to the type of the left side.
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: Division by zero makes the whole calc() expression invalid.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<CalculatedStyleValue::ResolvedType> CalculatedStyleValue::CalcProduct::resolved_type() const
|
||||||
|
{
|
||||||
|
auto maybe_type = first_calc_value.resolved_type();
|
||||||
|
if (!maybe_type.has_value())
|
||||||
|
return {};
|
||||||
|
auto type = maybe_type.value();
|
||||||
|
return resolve_product_type(type, zero_or_more_additional_calc_values);
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<CalculatedStyleValue::ResolvedType> CalculatedStyleValue::CalcSumPartWithOperator::resolved_type() const
|
||||||
|
{
|
||||||
|
return value->resolved_type();
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<CalculatedStyleValue::ResolvedType> CalculatedStyleValue::CalcNumberProduct::resolved_type() const
|
||||||
|
{
|
||||||
|
auto maybe_type = first_calc_number_value.resolved_type();
|
||||||
|
if (!maybe_type.has_value())
|
||||||
|
return {};
|
||||||
|
auto type = maybe_type.value();
|
||||||
|
return resolve_product_type(type, zero_or_more_additional_calc_number_values);
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<CalculatedStyleValue::ResolvedType> CalculatedStyleValue::CalcNumberProductPartWithOperator::resolved_type() const
|
||||||
|
{
|
||||||
|
return value.resolved_type();
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<CalculatedStyleValue::ResolvedType> CalculatedStyleValue::CalcNumberSumPartWithOperator::resolved_type() const
|
||||||
|
{
|
||||||
|
return value->resolved_type();
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<CalculatedStyleValue::ResolvedType> CalculatedStyleValue::CalcProductPartWithOperator::resolved_type() const
|
||||||
|
{
|
||||||
|
return value.visit(
|
||||||
|
[](CalcValue const& calc_value) {
|
||||||
|
return calc_value.resolved_type();
|
||||||
|
},
|
||||||
|
[](CalcNumberValue const& calc_number_value) {
|
||||||
|
return calc_number_value.resolved_type();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<CalculatedStyleValue::ResolvedType> CalculatedStyleValue::CalcValue::resolved_type() const
|
||||||
|
{
|
||||||
|
return value.visit(
|
||||||
|
[](float) -> Optional<CalculatedStyleValue::ResolvedType> { return { ResolvedType::Number }; },
|
||||||
|
[](Length const&) -> Optional<CalculatedStyleValue::ResolvedType> { return { ResolvedType::Length }; },
|
||||||
|
[](NonnullOwnPtr<CalcSum> const& sum) { return sum->resolved_type(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<CalculatedStyleValue::ResolvedType> CalculatedStyleValue::CalcNumberValue::resolved_type() const
|
||||||
|
{
|
||||||
|
return value.visit(
|
||||||
|
[](float) -> Optional<CalculatedStyleValue::ResolvedType> { return { ResolvedType::Number }; },
|
||||||
|
[](NonnullOwnPtr<CalcNumberSum> const& sum) { return sum->resolved_type(); });
|
||||||
|
}
|
||||||
|
|
||||||
// https://www.w3.org/TR/css-color-4/#serializing-sRGB-values
|
// https://www.w3.org/TR/css-color-4/#serializing-sRGB-values
|
||||||
String ColorStyleValue::to_string() const
|
String ColorStyleValue::to_string() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -654,6 +654,16 @@ private:
|
||||||
|
|
||||||
class CalculatedStyleValue : public StyleValue {
|
class CalculatedStyleValue : public StyleValue {
|
||||||
public:
|
public:
|
||||||
|
enum class ResolvedType {
|
||||||
|
Angle,
|
||||||
|
Frequency,
|
||||||
|
Integer,
|
||||||
|
Length,
|
||||||
|
Number,
|
||||||
|
Percentage,
|
||||||
|
Time,
|
||||||
|
};
|
||||||
|
|
||||||
struct CalcSum;
|
struct CalcSum;
|
||||||
struct CalcSumPartWithOperator;
|
struct CalcSumPartWithOperator;
|
||||||
struct CalcProduct;
|
struct CalcProduct;
|
||||||
|
@ -663,8 +673,15 @@ public:
|
||||||
struct CalcNumberProduct;
|
struct CalcNumberProduct;
|
||||||
struct CalcNumberProductPartWithOperator;
|
struct CalcNumberProductPartWithOperator;
|
||||||
|
|
||||||
using CalcNumberValue = Variant<float, NonnullOwnPtr<CalcNumberSum>>;
|
struct CalcNumberValue {
|
||||||
using CalcValue = Variant<float, CSS::Length, NonnullOwnPtr<CalcSum>>;
|
Variant<float, NonnullOwnPtr<CalcNumberSum>> value;
|
||||||
|
Optional<ResolvedType> resolved_type() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CalcValue {
|
||||||
|
Variant<float, CSS::Length, NonnullOwnPtr<CalcSum>> value;
|
||||||
|
Optional<ResolvedType> resolved_type() const;
|
||||||
|
};
|
||||||
|
|
||||||
enum class SumOperation {
|
enum class SumOperation {
|
||||||
Add,
|
Add,
|
||||||
|
@ -683,6 +700,8 @@ public:
|
||||||
|
|
||||||
NonnullOwnPtr<CalcProduct> first_calc_product;
|
NonnullOwnPtr<CalcProduct> first_calc_product;
|
||||||
NonnullOwnPtrVector<CalcSumPartWithOperator> zero_or_more_additional_calc_products;
|
NonnullOwnPtrVector<CalcSumPartWithOperator> zero_or_more_additional_calc_products;
|
||||||
|
|
||||||
|
Optional<ResolvedType> resolved_type() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CalcNumberSum {
|
struct CalcNumberSum {
|
||||||
|
@ -692,63 +711,80 @@ public:
|
||||||
|
|
||||||
NonnullOwnPtr<CalcNumberProduct> first_calc_number_product;
|
NonnullOwnPtr<CalcNumberProduct> first_calc_number_product;
|
||||||
NonnullOwnPtrVector<CalcNumberSumPartWithOperator> zero_or_more_additional_calc_number_products;
|
NonnullOwnPtrVector<CalcNumberSumPartWithOperator> zero_or_more_additional_calc_number_products;
|
||||||
|
|
||||||
|
Optional<ResolvedType> resolved_type() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CalcProduct {
|
struct CalcProduct {
|
||||||
CalcValue first_calc_value;
|
CalcValue first_calc_value;
|
||||||
NonnullOwnPtrVector<CalcProductPartWithOperator> zero_or_more_additional_calc_values;
|
NonnullOwnPtrVector<CalcProductPartWithOperator> zero_or_more_additional_calc_values;
|
||||||
|
|
||||||
|
Optional<ResolvedType> resolved_type() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CalcSumPartWithOperator {
|
struct CalcSumPartWithOperator {
|
||||||
CalcSumPartWithOperator(SumOperation op, NonnullOwnPtr<CalcProduct> calc_product)
|
CalcSumPartWithOperator(SumOperation op, NonnullOwnPtr<CalcProduct> calc_product)
|
||||||
: op(op)
|
: op(op)
|
||||||
, calc_product(move(calc_product)) {};
|
, value(move(calc_product)) {};
|
||||||
|
|
||||||
SumOperation op;
|
SumOperation op;
|
||||||
NonnullOwnPtr<CalcProduct> calc_product;
|
NonnullOwnPtr<CalcProduct> value;
|
||||||
|
|
||||||
|
Optional<ResolvedType> resolved_type() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CalcProductPartWithOperator {
|
struct CalcProductPartWithOperator {
|
||||||
ProductOperation op;
|
ProductOperation op;
|
||||||
Variant<CalcValue, CalcNumberValue> value;
|
Variant<CalcValue, CalcNumberValue> value;
|
||||||
|
|
||||||
|
Optional<ResolvedType> resolved_type() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CalcNumberProduct {
|
struct CalcNumberProduct {
|
||||||
CalcNumberValue first_calc_number_value;
|
CalcNumberValue first_calc_number_value;
|
||||||
NonnullOwnPtrVector<CalcNumberProductPartWithOperator> zero_or_more_additional_calc_number_values;
|
NonnullOwnPtrVector<CalcNumberProductPartWithOperator> zero_or_more_additional_calc_number_values;
|
||||||
|
|
||||||
|
Optional<ResolvedType> resolved_type() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CalcNumberProductPartWithOperator {
|
struct CalcNumberProductPartWithOperator {
|
||||||
ProductOperation op;
|
ProductOperation op;
|
||||||
CalcNumberValue value;
|
CalcNumberValue value;
|
||||||
|
|
||||||
|
Optional<ResolvedType> resolved_type() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CalcNumberSumPartWithOperator {
|
struct CalcNumberSumPartWithOperator {
|
||||||
CalcNumberSumPartWithOperator(SumOperation op, NonnullOwnPtr<CalcNumberProduct> calc_number_product)
|
CalcNumberSumPartWithOperator(SumOperation op, NonnullOwnPtr<CalcNumberProduct> calc_number_product)
|
||||||
: op(op)
|
: op(op)
|
||||||
, calc_number_product(move(calc_number_product)) {};
|
, value(move(calc_number_product)) {};
|
||||||
|
|
||||||
SumOperation op;
|
SumOperation op;
|
||||||
NonnullOwnPtr<CalcNumberProduct> calc_number_product;
|
NonnullOwnPtr<CalcNumberProduct> value;
|
||||||
|
|
||||||
|
Optional<ResolvedType> resolved_type() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
static NonnullRefPtr<CalculatedStyleValue> create(String const& expression_string, NonnullOwnPtr<CalcSum> calc_sum)
|
static NonnullRefPtr<CalculatedStyleValue> create(String const& expression_string, NonnullOwnPtr<CalcSum> calc_sum, ResolvedType resolved_type)
|
||||||
{
|
{
|
||||||
return adopt_ref(*new CalculatedStyleValue(expression_string, move(calc_sum)));
|
return adopt_ref(*new CalculatedStyleValue(expression_string, move(calc_sum), resolved_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
String to_string() const override { return m_expression_string; }
|
String to_string() const override { return m_expression_string; }
|
||||||
|
ResolvedType resolved_type() const { return m_resolved_type; }
|
||||||
NonnullOwnPtr<CalcSum> const& expression() const { return m_expression; }
|
NonnullOwnPtr<CalcSum> const& expression() const { return m_expression; }
|
||||||
Optional<Length> resolve_length(Layout::Node const& layout_node) const;
|
Optional<Length> resolve_length(Layout::Node const& layout_node) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit CalculatedStyleValue(String const& expression_string, NonnullOwnPtr<CalcSum> calc_sum)
|
explicit CalculatedStyleValue(String const& expression_string, NonnullOwnPtr<CalcSum> calc_sum, ResolvedType resolved_type)
|
||||||
: StyleValue(Type::Calculated)
|
: StyleValue(Type::Calculated)
|
||||||
|
, m_resolved_type(resolved_type)
|
||||||
, m_expression_string(expression_string)
|
, m_expression_string(expression_string)
|
||||||
, m_expression(move(calc_sum))
|
, m_expression(move(calc_sum))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResolvedType m_resolved_type;
|
||||||
String m_expression_string;
|
String m_expression_string;
|
||||||
NonnullOwnPtr<CalcSum> m_expression;
|
NonnullOwnPtr<CalcSum> m_expression;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue