mirror of
https://github.com/zebrajr/ladybird.git
synced 2025-12-06 00:19:53 +01:00
LibWeb: Absolutize StyleValues before computing font properties
We also avoid prematurely constructing CSSPixels when computing font-size which gains us a couple of test passes
This commit is contained in:
parent
ca9d107a1a
commit
28451b16c9
|
|
@ -18,7 +18,7 @@ struct CalculationResolutionContext {
|
|||
using PercentageBasis = Variant<Empty, Angle, Frequency, Length, Time>;
|
||||
|
||||
PercentageBasis percentage_basis {};
|
||||
Optional<Length::ResolutionContext> length_resolution_context;
|
||||
Optional<Length::ResolutionContext> length_resolution_context {};
|
||||
|
||||
static CalculationResolutionContext from_computation_context(ComputationContext const& computation_context, PercentageBasis percentage_basis = {})
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3381,29 +3381,31 @@ NonnullRefPtr<StyleValue const> StyleComputer::compute_font_size(NonnullRefPtr<S
|
|||
// https://drafts.csswg.org/css-fonts/#font-size-prop
|
||||
// an absolute length
|
||||
|
||||
auto const& absolutized_value = specified_value->absolutized(computation_context);
|
||||
|
||||
// <absolute-size>
|
||||
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())));
|
||||
|
||||
// <relative-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)));
|
||||
|
||||
// <length-percentage [0,∞]>
|
||||
// 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<StyleValue const> StyleComputer::compute_font_size(NonnullRefPtr<S
|
|||
return 1.0 / scale;
|
||||
}();
|
||||
|
||||
return LengthStyleValue::create(Length::make_px(inherited_font_size.scale_by(math_scaling_factor)));
|
||||
return LengthStyleValue::create(Length::make_px(inherited_font_size.scaled(math_scaling_factor)));
|
||||
}
|
||||
|
||||
VERIFY_NOT_REACHED();
|
||||
|
|
@ -3473,22 +3475,24 @@ NonnullRefPtr<StyleValue const> 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);
|
||||
|
||||
// <number [1,1000]>
|
||||
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<StyleValue const> 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<StyleValue const> 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<StyleValue const> 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);
|
||||
|
||||
// <percentage [0,∞]>
|
||||
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<StyleValue const> StyleComputer::compute_font_width(NonnullRefPtr<
|
|||
NonnullRefPtr<StyleValue const> StyleComputer::compute_line_height(NonnullRefPtr<StyleValue const> 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
|
||||
// <length [0,∞]>
|
||||
if (specified_value->is_length())
|
||||
return specified_value->absolutized(computation_context);
|
||||
// <number [0,∞]>
|
||||
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());
|
||||
|
||||
// <number [0,∞]>
|
||||
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());
|
||||
|
||||
// <percentage [0,∞]>
|
||||
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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,6 +127,10 @@ private:
|
|||
double value;
|
||||
Optional<NumericType> 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<ResolvedValue> resolve_value(CalculationResolutionContext const&) const;
|
||||
|
||||
Optional<ValueType> percentage_resolved_type() const;
|
||||
|
|
|
|||
|
|
@ -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<CanvasType, HTML::HTMLCanvasElement>) {
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@ Harness status: OK
|
|||
|
||||
Found 140 tests
|
||||
|
||||
136 Pass
|
||||
4 Fail
|
||||
140 Pass
|
||||
Pass CSS Transitions: property <font-size> from neutral to [20px] at (-2) should be [0px]
|
||||
Pass CSS Transitions: property <font-size> from neutral to [20px] at (-0.3) should be [7px]
|
||||
Pass CSS Transitions: property <font-size> from neutral to [20px] at (0) should be [10px]
|
||||
|
|
@ -36,28 +35,28 @@ Pass CSS Transitions: property <font-size> from [initial] to [20px] at (-2) shou
|
|||
Pass CSS Transitions: property <font-size> from [initial] to [20px] at (-0.3) should be [14.8px]
|
||||
Pass CSS Transitions: property <font-size> from [initial] to [20px] at (0) should be [16px]
|
||||
Pass CSS Transitions: property <font-size> from [initial] to [20px] at (0.3) should be [17.2px]
|
||||
Fail CSS Transitions: property <font-size> from [initial] to [20px] at (0.6) should be [18.4px]
|
||||
Pass CSS Transitions: property <font-size> from [initial] to [20px] at (0.6) should be [18.4px]
|
||||
Pass CSS Transitions: property <font-size> from [initial] to [20px] at (1) should be [20px]
|
||||
Pass CSS Transitions: property <font-size> from [initial] to [20px] at (1.5) should be [22px]
|
||||
Pass CSS Transitions with transition: all: property <font-size> from [initial] to [20px] at (-2) should be [8px]
|
||||
Pass CSS Transitions with transition: all: property <font-size> from [initial] to [20px] at (-0.3) should be [14.8px]
|
||||
Pass CSS Transitions with transition: all: property <font-size> from [initial] to [20px] at (0) should be [16px]
|
||||
Pass CSS Transitions with transition: all: property <font-size> from [initial] to [20px] at (0.3) should be [17.2px]
|
||||
Fail CSS Transitions with transition: all: property <font-size> from [initial] to [20px] at (0.6) should be [18.4px]
|
||||
Pass CSS Transitions with transition: all: property <font-size> from [initial] to [20px] at (0.6) should be [18.4px]
|
||||
Pass CSS Transitions with transition: all: property <font-size> from [initial] to [20px] at (1) should be [20px]
|
||||
Pass CSS Transitions with transition: all: property <font-size> from [initial] to [20px] at (1.5) should be [22px]
|
||||
Pass CSS Animations: property <font-size> from [initial] to [20px] at (-2) should be [8px]
|
||||
Pass CSS Animations: property <font-size> from [initial] to [20px] at (-0.3) should be [14.8px]
|
||||
Pass CSS Animations: property <font-size> from [initial] to [20px] at (0) should be [16px]
|
||||
Pass CSS Animations: property <font-size> from [initial] to [20px] at (0.3) should be [17.2px]
|
||||
Fail CSS Animations: property <font-size> from [initial] to [20px] at (0.6) should be [18.4px]
|
||||
Pass CSS Animations: property <font-size> from [initial] to [20px] at (0.6) should be [18.4px]
|
||||
Pass CSS Animations: property <font-size> from [initial] to [20px] at (1) should be [20px]
|
||||
Pass CSS Animations: property <font-size> from [initial] to [20px] at (1.5) should be [22px]
|
||||
Pass Web Animations: property <font-size> from [initial] to [20px] at (-2) should be [8px]
|
||||
Pass Web Animations: property <font-size> from [initial] to [20px] at (-0.3) should be [14.8px]
|
||||
Pass Web Animations: property <font-size> from [initial] to [20px] at (0) should be [16px]
|
||||
Pass Web Animations: property <font-size> from [initial] to [20px] at (0.3) should be [17.2px]
|
||||
Fail Web Animations: property <font-size> from [initial] to [20px] at (0.6) should be [18.4px]
|
||||
Pass Web Animations: property <font-size> from [initial] to [20px] at (0.6) should be [18.4px]
|
||||
Pass Web Animations: property <font-size> from [initial] to [20px] at (1) should be [20px]
|
||||
Pass Web Animations: property <font-size> from [initial] to [20px] at (1.5) should be [22px]
|
||||
Pass CSS Transitions: property <font-size> from [inherit] to [20px] at (-2) should be [50px]
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user