diff --git a/Libraries/LibWeb/CSS/CalculationResolutionContext.h b/Libraries/LibWeb/CSS/CalculationResolutionContext.h index 7260e6939a7..d8a4402927e 100644 --- a/Libraries/LibWeb/CSS/CalculationResolutionContext.h +++ b/Libraries/LibWeb/CSS/CalculationResolutionContext.h @@ -18,7 +18,7 @@ struct CalculationResolutionContext { using PercentageBasis = Variant; PercentageBasis percentage_basis {}; - Optional length_resolution_context; + Optional length_resolution_context {}; static CalculationResolutionContext from_computation_context(ComputationContext const& computation_context, PercentageBasis percentage_basis = {}) { diff --git a/Libraries/LibWeb/CSS/StyleComputer.cpp b/Libraries/LibWeb/CSS/StyleComputer.cpp index eb48ccbedb0..f19dfe8ed88 100644 --- a/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -3381,29 +3381,31 @@ NonnullRefPtr StyleComputer::compute_font_size(NonnullRefPtrabsolutized(computation_context); + // - if (auto absolute_size = keyword_to_absolute_size(specified_value->to_keyword()); absolute_size.has_value()) + if (auto absolute_size = keyword_to_absolute_size(absolutized_value->to_keyword()); absolute_size.has_value()) return LengthStyleValue::create(Length::make_px(absolute_size_mapping(absolute_size.value(), default_user_font_size()))); // - if (auto relative_size = keyword_to_relative_size(specified_value->to_keyword()); relative_size.has_value()) + if (auto relative_size = keyword_to_relative_size(absolutized_value->to_keyword()); relative_size.has_value()) return LengthStyleValue::create(Length::make_px(relative_size_mapping(relative_size.value(), inherited_font_size))); // // A length value specifies an absolute font size (independent of the user agent’s font table). Negative lengths are invalid. - if (specified_value->is_length()) - return LengthStyleValue::create(Length::make_px(max(CSSPixels { 0 }, specified_value->as_length().length().to_px(computation_context.length_resolution_context)))); + if (absolutized_value->is_length()) + return absolutized_value; // A percentage value specifies an absolute font size relative to the parent element’s computed font-size. Negative percentages are invalid. - if (specified_value->is_percentage()) - return LengthStyleValue::create(Length::make_px(inherited_font_size * specified_value->as_percentage().percentage().as_fraction())); + if (absolutized_value->is_percentage()) + return LengthStyleValue::create(Length::make_px(inherited_font_size * absolutized_value->as_percentage().percentage().as_fraction())); - if (specified_value->is_calculated()) - return LengthStyleValue::create(specified_value->as_calculated().resolve_length(CalculationResolutionContext::from_computation_context(computation_context, Length(1, LengthUnit::Em))).value()); + if (absolutized_value->is_calculated()) + return LengthStyleValue::create(absolutized_value->as_calculated().resolve_length({ .percentage_basis = Length::make_px(inherited_font_size) }).value()); // math // Special mathematical scaling rules must be applied when determining the computed value of the font-size property. - if (specified_value->to_keyword() == Keyword::Math) { + if (absolutized_value->to_keyword() == Keyword::Math) { auto math_scaling_factor = [&]() { // https://w3c.github.io/mathml-core/#the-math-script-level-property // If the specified value font-size is math then the computed value of font-size is obtained by multiplying @@ -3439,7 +3441,7 @@ NonnullRefPtr StyleComputer::compute_font_size(NonnullRefPtr StyleComputer::compute_font_weight(NonnullRefPtr // https://drafts.csswg.org/css-fonts-4/#font-weight-prop // a number, see below + auto const& absolutized_value = specified_value->absolutized(computation_context); + // - if (specified_value->is_number()) - return specified_value; + if (absolutized_value->is_number()) + return absolutized_value; // AD-HOC: Anywhere we support a numbers we should also support calcs - if (specified_value->is_calculated()) - return NumberStyleValue::create(specified_value->as_calculated().resolve_number(CalculationResolutionContext::from_computation_context(computation_context)).value()); + if (absolutized_value->is_calculated()) + return NumberStyleValue::create(absolutized_value->as_calculated().resolve_number({}).value()); // normal // Same as 400. - if (specified_value->to_keyword() == Keyword::Normal) + if (absolutized_value->to_keyword() == Keyword::Normal) return NumberStyleValue::create(400); // bold // Same as 700. - if (specified_value->to_keyword() == Keyword::Bold) + if (absolutized_value->to_keyword() == Keyword::Bold) return NumberStyleValue::create(700); // Specified values of bolder and lighter indicate weights relative to the weight of the parent element. The @@ -3504,7 +3508,7 @@ NonnullRefPtr StyleComputer::compute_font_weight(NonnullRefPtr // bolder // Specifies a bolder weight than the inherited value. See § 2.2.1 Relative Weights. - if (specified_value->to_keyword() == Keyword::Bolder) { + if (absolutized_value->to_keyword() == Keyword::Bolder) { if (inherited_font_weight < 350) return NumberStyleValue::create(400); @@ -3519,7 +3523,7 @@ NonnullRefPtr StyleComputer::compute_font_weight(NonnullRefPtr // lighter // Specifies a lighter weight than the inherited value. See § 2.2.1 Relative Weights. - if (specified_value->to_keyword() == Keyword::Lighter) { + if (absolutized_value->to_keyword() == Keyword::Lighter) { if (inherited_font_weight < 100) return NumberStyleValue::create(inherited_font_weight); @@ -3540,15 +3544,17 @@ NonnullRefPtr StyleComputer::compute_font_width(NonnullRefPtr< // https://drafts.csswg.org/css-fonts-4/#font-width-prop // a percentage, see below + auto absolutized_value = specified_value->absolutized(computation_context); + // - if (specified_value->is_percentage()) - return specified_value; + if (absolutized_value->is_percentage()) + return absolutized_value; // AD-HOC: We support calculated percentages as well - if (specified_value->is_calculated()) - return PercentageStyleValue::create(specified_value->as_calculated().resolve_percentage(CalculationResolutionContext::from_computation_context(computation_context)).value()); + if (absolutized_value->is_calculated()) + return PercentageStyleValue::create(absolutized_value->as_calculated().resolve_percentage({}).value()); - switch (specified_value->to_keyword()) { + switch (absolutized_value->to_keyword()) { // ultra-condensed 50% case Keyword::UltraCondensed: return PercentageStyleValue::create(Percentage(50)); @@ -3584,29 +3590,26 @@ NonnullRefPtr StyleComputer::compute_font_width(NonnullRefPtr< NonnullRefPtr StyleComputer::compute_line_height(NonnullRefPtr const& specified_value, ComputationContext const& computation_context) { // https://drafts.csswg.org/css-inline-3/#line-height-property - // normal - if (specified_value->to_keyword() == Keyword::Normal) - return specified_value; + auto absolutized_value = specified_value->absolutized(computation_context); + + // normal // - if (specified_value->is_length()) - return specified_value->absolutized(computation_context); + // + if (absolutized_value->to_keyword() == Keyword::Normal || absolutized_value->is_length() || absolutized_value->is_number()) + return absolutized_value; // NOTE: We also support calc()'d lengths (percentages resolve to lengths so we don't have to handle them separately) - if (specified_value->is_calculated() && specified_value->as_calculated().resolves_to_length_percentage()) - return LengthStyleValue::create(specified_value->as_calculated().resolve_length(CalculationResolutionContext::from_computation_context(computation_context, Length(1, LengthUnit::Em))).value()); - - // - if (specified_value->is_number()) - return specified_value; + if (absolutized_value->is_calculated() && absolutized_value->as_calculated().resolves_to_length_percentage()) + return LengthStyleValue::create(absolutized_value->as_calculated().resolve_length({ .percentage_basis = Length::make_px(computation_context.length_resolution_context.font_metrics.font_size) }).value()); // NOTE: We also support calc()'d numbers - if (specified_value->is_calculated() && specified_value->as_calculated().resolves_to_number()) - return NumberStyleValue::create(specified_value->as_calculated().resolve_number(CalculationResolutionContext::from_computation_context(computation_context, Length(1, LengthUnit::Em))).value()); + if (absolutized_value->is_calculated() && absolutized_value->as_calculated().resolves_to_number()) + return NumberStyleValue::create(absolutized_value->as_calculated().resolve_number({ .percentage_basis = Length::make_px(computation_context.length_resolution_context.font_metrics.font_size) }).value()); // - if (specified_value->is_percentage()) - return LengthStyleValue::create(Length::make_px(computation_context.length_resolution_context.font_metrics.font_size * specified_value->as_percentage().percentage().as_fraction())); + if (absolutized_value->is_percentage()) + return LengthStyleValue::create(Length::make_px(computation_context.length_resolution_context.font_metrics.font_size * absolutized_value->as_percentage().percentage().as_fraction())); VERIFY_NOT_REACHED(); } diff --git a/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.h b/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.h index 0ee2d6bb839..2400b2cbdb6 100644 --- a/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.h +++ b/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.h @@ -127,6 +127,10 @@ private: double value; Optional type; }; + // FIXME: Calculations should be simplified apart from percentages by the absolutized method prior to this method + // being called so we can take just the percentage_basis rather than a full CalculationResolutionContext. + // There are still some CalculatedStyleValues which we don't call absolutized for (i.e. sub-values of other + // StyleValue classes which lack their own absolutized method) which will need to be fixed beforehand. Optional resolve_value(CalculationResolutionContext const&) const; Optional percentage_resolved_type() const; diff --git a/Libraries/LibWeb/HTML/Canvas/CanvasTextDrawingStyles.h b/Libraries/LibWeb/HTML/Canvas/CanvasTextDrawingStyles.h index 76b7c3646b8..59e8f531fd4 100644 --- a/Libraries/LibWeb/HTML/Canvas/CanvasTextDrawingStyles.h +++ b/Libraries/LibWeb/HTML/Canvas/CanvasTextDrawingStyles.h @@ -112,6 +112,8 @@ public: // NOTE: The initial value here is non-standard as the default font is "10px sans-serif" auto inherited_font_size = CSSPixels { 10 }; auto inherited_font_weight = CSS::InitialValues::font_weight(); + // FIXME: Investigate whether this is the correct resolution context (i.e. whether we should instead use + // a font-size of 10px) for OffscreenCanvas auto length_resolution_context = CSS::Length::ResolutionContext::for_window(*document->window()); if constexpr (SameAs) { diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-fonts/animations/font-size-interpolation-001.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-fonts/animations/font-size-interpolation-001.txt index d6fc6469310..dd181b84e53 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-fonts/animations/font-size-interpolation-001.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-fonts/animations/font-size-interpolation-001.txt @@ -2,8 +2,7 @@ Harness status: OK Found 140 tests -136 Pass -4 Fail +140 Pass Pass CSS Transitions: property from neutral to [20px] at (-2) should be [0px] Pass CSS Transitions: property from neutral to [20px] at (-0.3) should be [7px] Pass CSS Transitions: property from neutral to [20px] at (0) should be [10px] @@ -36,28 +35,28 @@ Pass CSS Transitions: property from [initial] to [20px] at (-2) shou Pass CSS Transitions: property from [initial] to [20px] at (-0.3) should be [14.8px] Pass CSS Transitions: property from [initial] to [20px] at (0) should be [16px] Pass CSS Transitions: property from [initial] to [20px] at (0.3) should be [17.2px] -Fail CSS Transitions: property from [initial] to [20px] at (0.6) should be [18.4px] +Pass CSS Transitions: property from [initial] to [20px] at (0.6) should be [18.4px] Pass CSS Transitions: property from [initial] to [20px] at (1) should be [20px] Pass CSS Transitions: property from [initial] to [20px] at (1.5) should be [22px] Pass CSS Transitions with transition: all: property from [initial] to [20px] at (-2) should be [8px] Pass CSS Transitions with transition: all: property from [initial] to [20px] at (-0.3) should be [14.8px] Pass CSS Transitions with transition: all: property from [initial] to [20px] at (0) should be [16px] Pass CSS Transitions with transition: all: property from [initial] to [20px] at (0.3) should be [17.2px] -Fail CSS Transitions with transition: all: property from [initial] to [20px] at (0.6) should be [18.4px] +Pass CSS Transitions with transition: all: property from [initial] to [20px] at (0.6) should be [18.4px] Pass CSS Transitions with transition: all: property from [initial] to [20px] at (1) should be [20px] Pass CSS Transitions with transition: all: property from [initial] to [20px] at (1.5) should be [22px] Pass CSS Animations: property from [initial] to [20px] at (-2) should be [8px] Pass CSS Animations: property from [initial] to [20px] at (-0.3) should be [14.8px] Pass CSS Animations: property from [initial] to [20px] at (0) should be [16px] Pass CSS Animations: property from [initial] to [20px] at (0.3) should be [17.2px] -Fail CSS Animations: property from [initial] to [20px] at (0.6) should be [18.4px] +Pass CSS Animations: property from [initial] to [20px] at (0.6) should be [18.4px] Pass CSS Animations: property from [initial] to [20px] at (1) should be [20px] Pass CSS Animations: property from [initial] to [20px] at (1.5) should be [22px] Pass Web Animations: property from [initial] to [20px] at (-2) should be [8px] Pass Web Animations: property from [initial] to [20px] at (-0.3) should be [14.8px] Pass Web Animations: property from [initial] to [20px] at (0) should be [16px] Pass Web Animations: property from [initial] to [20px] at (0.3) should be [17.2px] -Fail Web Animations: property from [initial] to [20px] at (0.6) should be [18.4px] +Pass Web Animations: property from [initial] to [20px] at (0.6) should be [18.4px] Pass Web Animations: property from [initial] to [20px] at (1) should be [20px] Pass Web Animations: property from [initial] to [20px] at (1.5) should be [22px] Pass CSS Transitions: property from [inherit] to [20px] at (-2) should be [50px]