mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 22:38:13 +00:00
LibWeb: Use CSSNumericType for CalculatedStyleValue resolved type
This commit is contained in:
parent
4d84080fdc
commit
f21a30e45f
4 changed files with 54 additions and 60 deletions
|
@ -3407,32 +3407,12 @@ ErrorOr<RefPtr<CalculatedStyleValue>> Parser::parse_calculated_value(Vector<Comp
|
|||
}
|
||||
}
|
||||
|
||||
auto calc_type = calculation_tree->resolved_type();
|
||||
auto calc_type = calculation_tree->determine_type(m_context.current_property_id());
|
||||
if (!calc_type.has_value()) {
|
||||
dbgln_if(CSS_PARSER_DEBUG, "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()));
|
||||
dbgln_if(CSS_PARSER_DEBUG, "Deduced calc() resolved type as: {}", calc_type->dump());
|
||||
|
||||
return CalculatedStyleValue::create(calculation_tree.release_nonnull(), calc_type.release_value());
|
||||
}
|
||||
|
@ -4127,7 +4107,7 @@ ErrorOr<RefPtr<StyleValue>> Parser::parse_dynamic_value(ComponentValue const& co
|
|||
if (!function_node)
|
||||
return nullptr;
|
||||
|
||||
auto function_type = function_node->resolved_type();
|
||||
auto function_type = function_node->determine_type(m_context.current_property_id());
|
||||
if (!function_type.has_value())
|
||||
return nullptr;
|
||||
|
||||
|
@ -8266,6 +8246,13 @@ ErrorOr<Parser::PropertyAndValue> Parser::parse_css_value_for_properties(Readonl
|
|||
}
|
||||
return {};
|
||||
};
|
||||
auto any_property_accepts_type_percentage = [](ReadonlySpan<PropertyID> property_ids, ValueType value_type) -> Optional<PropertyID> {
|
||||
for (auto const& property : property_ids) {
|
||||
if (property_accepts_type(property, value_type) && property_accepts_type(property, ValueType::Percentage))
|
||||
return property;
|
||||
}
|
||||
return {};
|
||||
};
|
||||
auto any_property_accepts_identifier = [](ReadonlySpan<PropertyID> property_ids, ValueID identifier) -> Optional<PropertyID> {
|
||||
for (auto const& property : property_ids) {
|
||||
if (property_accepts_identifier(property, identifier))
|
||||
|
@ -8416,34 +8403,41 @@ ErrorOr<Parser::PropertyAndValue> Parser::parse_css_value_for_properties(Readonl
|
|||
if (auto maybe_dynamic = TRY(parse_dynamic_value(peek_token)); maybe_dynamic && maybe_dynamic->is_calculated()) {
|
||||
(void)tokens.next_token();
|
||||
auto& calculated = maybe_dynamic->as_calculated();
|
||||
switch (calculated.resolved_type()) {
|
||||
case CalculatedStyleValue::ResolvedType::Angle:
|
||||
if (calculated.resolves_to_angle_percentage()) {
|
||||
if (auto property = any_property_accepts_type_percentage(property_ids, ValueType::Angle); property.has_value())
|
||||
return PropertyAndValue { *property, calculated };
|
||||
} else if (calculated.resolves_to_angle()) {
|
||||
if (auto property = any_property_accepts_type(property_ids, ValueType::Angle); property.has_value())
|
||||
return PropertyAndValue { *property, calculated };
|
||||
break;
|
||||
case CalculatedStyleValue::ResolvedType::Frequency:
|
||||
} else if (calculated.resolves_to_frequency_percentage()) {
|
||||
if (auto property = any_property_accepts_type_percentage(property_ids, ValueType::Frequency); property.has_value())
|
||||
return PropertyAndValue { *property, calculated };
|
||||
} else if (calculated.resolves_to_frequency()) {
|
||||
if (auto property = any_property_accepts_type(property_ids, ValueType::Frequency); property.has_value())
|
||||
return PropertyAndValue { *property, calculated };
|
||||
break;
|
||||
case CalculatedStyleValue::ResolvedType::Integer:
|
||||
case CalculatedStyleValue::ResolvedType::Number:
|
||||
} else if (calculated.resolves_to_number_percentage()) {
|
||||
if (auto property = any_property_accepts_type_percentage(property_ids, ValueType::Number); property.has_value())
|
||||
return PropertyAndValue { *property, calculated };
|
||||
} else if (calculated.resolves_to_number()) {
|
||||
if (property_accepts_numeric) {
|
||||
auto property_or_resolved = property_accepting_integer.value_or_lazy_evaluated([property_accepting_number]() { return property_accepting_number.value(); });
|
||||
return PropertyAndValue { property_or_resolved, calculated };
|
||||
}
|
||||
break;
|
||||
case CalculatedStyleValue::ResolvedType::Length:
|
||||
} else if (calculated.resolves_to_length_percentage()) {
|
||||
if (auto property = any_property_accepts_type_percentage(property_ids, ValueType::Length); property.has_value())
|
||||
return PropertyAndValue { *property, calculated };
|
||||
} else if (calculated.resolves_to_length()) {
|
||||
if (auto property = any_property_accepts_type(property_ids, ValueType::Length); property.has_value())
|
||||
return PropertyAndValue { *property, calculated };
|
||||
break;
|
||||
case CalculatedStyleValue::ResolvedType::Percentage:
|
||||
if (auto property = any_property_accepts_type(property_ids, ValueType::Percentage); property.has_value())
|
||||
} else if (calculated.resolves_to_time_percentage()) {
|
||||
if (auto property = any_property_accepts_type_percentage(property_ids, ValueType::Time); property.has_value())
|
||||
return PropertyAndValue { *property, calculated };
|
||||
break;
|
||||
case CalculatedStyleValue::ResolvedType::Time:
|
||||
} else if (calculated.resolves_to_time()) {
|
||||
if (auto property = any_property_accepts_type(property_ids, ValueType::Time); property.has_value())
|
||||
return PropertyAndValue { *property, calculated };
|
||||
break;
|
||||
} else if (calculated.resolves_to_percentage()) {
|
||||
if (auto property = any_property_accepts_type(property_ids, ValueType::Percentage); property.has_value())
|
||||
return PropertyAndValue { *property, calculated };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -820,7 +820,7 @@ bool StyleComputer::expand_variables(DOM::Element& element, Optional<CSS::Select
|
|||
{
|
||||
// Arbitrary large value chosen to avoid the billion-laughs attack.
|
||||
// https://www.w3.org/TR/css-variables-1/#long-variables
|
||||
const size_t MAX_VALUE_COUNT = 16384;
|
||||
size_t const MAX_VALUE_COUNT = 16384;
|
||||
if (source.remaining_token_count() + dest.size() > MAX_VALUE_COUNT) {
|
||||
dbgln("Stopped expanding CSS variables: maximum length reached.");
|
||||
return false;
|
||||
|
@ -952,23 +952,20 @@ bool StyleComputer::expand_unresolved_values(DOM::Element& element, StringView p
|
|||
return false;
|
||||
}
|
||||
|
||||
// FIXME: Handle all math functions.
|
||||
if (value.function().name().equals_ignoring_ascii_case("calc"sv)) {
|
||||
auto const& calc_function = value.function();
|
||||
if (auto calc_value = Parser::Parser::parse_calculated_value({}, Parser::ParsingContext { document() }, calc_function.values()).release_value_but_fixme_should_propagate_errors()) {
|
||||
switch (calc_value->resolved_type()) {
|
||||
case CalculatedStyleValue::ResolvedType::Integer: {
|
||||
auto resolved_value = calc_value->resolve_integer();
|
||||
if (calc_value->resolves_to_number()) {
|
||||
auto resolved_value = calc_value->resolve_number();
|
||||
dest.empend(Parser::Token::create_number(resolved_value.value()));
|
||||
continue;
|
||||
}
|
||||
case CalculatedStyleValue::ResolvedType::Percentage: {
|
||||
} else if (calc_value->resolves_to_percentage()) {
|
||||
auto resolved_value = calc_value->resolve_percentage();
|
||||
dest.empend(Parser::Token::create_percentage(resolved_value.value().value()));
|
||||
continue;
|
||||
}
|
||||
default:
|
||||
} else {
|
||||
dbgln_if(LIBWEB_CSS_DEBUG, "FIXME: Unimplemented calc() expansion: {}", calc_value->to_string());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -265,13 +265,13 @@ static float resolve_opacity_value(CSS::StyleValue const& value)
|
|||
unclamped_opacity = value.as_number().number();
|
||||
} else if (value.is_calculated()) {
|
||||
auto& calculated = value.as_calculated();
|
||||
if (calculated.resolved_type() == CalculatedStyleValue::ResolvedType::Percentage) {
|
||||
if (calculated.resolves_to_percentage()) {
|
||||
auto maybe_percentage = value.as_calculated().resolve_percentage();
|
||||
if (maybe_percentage.has_value())
|
||||
unclamped_opacity = maybe_percentage->as_fraction();
|
||||
else
|
||||
dbgln("Unable to resolve calc() as opacity (percentage): {}", value.to_string());
|
||||
} else {
|
||||
} else if (calculated.resolves_to_number()) {
|
||||
auto maybe_number = const_cast<CalculatedStyleValue&>(value.as_calculated()).resolve_number();
|
||||
if (maybe_number.has_value())
|
||||
unclamped_opacity = maybe_number.value();
|
||||
|
|
|
@ -65,51 +65,54 @@ public:
|
|||
Value m_value;
|
||||
};
|
||||
|
||||
static ErrorOr<ValueComparingNonnullRefPtr<CalculatedStyleValue>> create(NonnullOwnPtr<CalculationNode> calculation, ResolvedType resolved_type)
|
||||
static ErrorOr<ValueComparingNonnullRefPtr<CalculatedStyleValue>> create(NonnullOwnPtr<CalculationNode> calculation, CSSNumericType resolved_type)
|
||||
{
|
||||
return adopt_nonnull_ref_or_enomem(new (nothrow) CalculatedStyleValue(move(calculation), resolved_type));
|
||||
}
|
||||
|
||||
ErrorOr<String> to_string() const override;
|
||||
virtual bool equals(StyleValue const& other) const override;
|
||||
ResolvedType resolved_type() const { return m_resolved_type; }
|
||||
|
||||
bool resolves_to_angle() const { return m_resolved_type == ResolvedType::Angle; }
|
||||
bool resolves_to_angle() const { return m_resolved_type.matches_angle(); }
|
||||
bool resolves_to_angle_percentage() const { return m_resolved_type.matches_angle_percentage(); }
|
||||
Optional<Angle> resolve_angle() const;
|
||||
Optional<Angle> resolve_angle_percentage(Angle const& percentage_basis) const;
|
||||
|
||||
bool resolves_to_frequency() const { return m_resolved_type == ResolvedType::Frequency; }
|
||||
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;
|
||||
Optional<Frequency> resolve_frequency_percentage(Frequency const& percentage_basis) const;
|
||||
|
||||
bool resolves_to_length() const { return m_resolved_type == ResolvedType::Length; }
|
||||
bool resolves_to_length() const { return m_resolved_type.matches_length(); }
|
||||
bool resolves_to_length_percentage() const { return m_resolved_type.matches_length_percentage(); }
|
||||
[[nodiscard]] Optional<Length> resolve_length(Length::ResolutionContext const&) const;
|
||||
Optional<Length> resolve_length(Layout::Node const& layout_node) const;
|
||||
Optional<Length> resolve_length_percentage(Layout::Node const&, Length const& percentage_basis) const;
|
||||
|
||||
bool resolves_to_percentage() const { return m_resolved_type == ResolvedType::Percentage; }
|
||||
bool resolves_to_percentage() const { return m_resolved_type.matches_percentage(); }
|
||||
Optional<Percentage> resolve_percentage() const;
|
||||
|
||||
bool resolves_to_time() const { return m_resolved_type == ResolvedType::Time; }
|
||||
bool resolves_to_time() const { return m_resolved_type.matches_time(); }
|
||||
bool resolves_to_time_percentage() const { return m_resolved_type.matches_time_percentage(); }
|
||||
Optional<Time> resolve_time() const;
|
||||
Optional<Time> resolve_time_percentage(Time const& percentage_basis) const;
|
||||
|
||||
bool resolves_to_integer() const { return m_resolved_type == ResolvedType::Integer; }
|
||||
bool resolves_to_number() const { return resolves_to_integer() || m_resolved_type == ResolvedType::Number; }
|
||||
bool resolves_to_number() const { return m_resolved_type.matches_number(); }
|
||||
bool resolves_to_number_percentage() const { return m_resolved_type.matches_number_percentage(); }
|
||||
Optional<double> resolve_number() const;
|
||||
Optional<i64> resolve_integer();
|
||||
|
||||
bool contains_percentage() const;
|
||||
|
||||
private:
|
||||
explicit CalculatedStyleValue(NonnullOwnPtr<CalculationNode> calculation, ResolvedType resolved_type)
|
||||
explicit CalculatedStyleValue(NonnullOwnPtr<CalculationNode> calculation, CSSNumericType resolved_type)
|
||||
: StyleValue(Type::Calculated)
|
||||
, m_resolved_type(resolved_type)
|
||||
, m_calculation(move(calculation))
|
||||
{
|
||||
}
|
||||
|
||||
ResolvedType m_resolved_type;
|
||||
CSSNumericType m_resolved_type;
|
||||
NonnullOwnPtr<CalculationNode> m_calculation;
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue