LibWeb: Separate relative sizes from absolute_size_mapping

Having relative sizes handled in this function was misleading
This commit is contained in:
Callum Law 2025-08-29 17:52:45 +12:00 committed by Sam Atkins
commit d6754307f9
Notes: github-actions[bot] 2025-09-19 09:09:15 +00:00
5 changed files with 88 additions and 42 deletions

View file

@ -1,4 +1,14 @@
{ {
"absolute-size": [
"xx-small",
"x-small",
"small",
"medium",
"large",
"x-large",
"xx-large",
"xxx-large"
],
"align-content": [ "align-content": [
"normal", "normal",
"start", "start",
@ -615,6 +625,10 @@
"strict-origin-when-cross-origin", "strict-origin-when-cross-origin",
"unsafe-url" "unsafe-url"
], ],
"relative-size": [
"smaller",
"larger"
],
"repetition": [ "repetition": [
"no-repeat", "no-repeat",
"repeat", "repeat",

View file

@ -1663,19 +1663,11 @@
"initial": "medium", "initial": "medium",
"valid-types": [ "valid-types": [
"length [0,∞]", "length [0,∞]",
"percentage [0,∞]" "percentage [0,∞]",
"absolute-size",
"relative-size"
], ],
"valid-identifiers": [ "valid-identifiers": [
"large",
"larger",
"medium",
"small",
"smaller",
"x-large",
"x-small",
"xx-large",
"xx-small",
"xxx-large",
"math" "math"
], ],
"percentages-resolve-to": "length", "percentages-resolve-to": "length",

View file

@ -1762,32 +1762,53 @@ CSSPixels StyleComputer::default_user_font_size()
} }
// https://w3c.github.io/csswg-drafts/css-fonts/#absolute-size-mapping // https://w3c.github.io/csswg-drafts/css-fonts/#absolute-size-mapping
CSSPixelFraction StyleComputer::absolute_size_mapping(Keyword keyword) CSSPixels StyleComputer::absolute_size_mapping(AbsoluteSize absolute_size, CSSPixels default_font_size)
{ {
switch (keyword) { // An <absolute-size> keyword refers to an entry in a table of font sizes computed and kept by the user agent. See
case Keyword::XxSmall: // §2.5.1 Absolute Size Keyword Mapping Table.
return CSSPixels(3) / 5; switch (absolute_size) {
case Keyword::XSmall: case AbsoluteSize::XxSmall:
return CSSPixels(3) / 4; return default_font_size * CSSPixels(3) / 5;
case Keyword::Small: case AbsoluteSize::XSmall:
return CSSPixels(8) / 9; return default_font_size * CSSPixels(3) / 4;
case Keyword::Medium: case AbsoluteSize::Small:
return 1; return default_font_size * CSSPixels(8) / 9;
case Keyword::Large: case AbsoluteSize::Medium:
return CSSPixels(6) / 5; return default_font_size;
case Keyword::XLarge: case AbsoluteSize::Large:
return CSSPixels(3) / 2; return default_font_size * CSSPixels(6) / 5;
case Keyword::XxLarge: case AbsoluteSize::XLarge:
return 2; return default_font_size * CSSPixels(3) / 2;
case Keyword::XxxLarge: case AbsoluteSize::XxLarge:
return 3; return default_font_size * 2;
case Keyword::Smaller: case AbsoluteSize::XxxLarge:
return CSSPixels(4) / 5; return default_font_size * 3;
case Keyword::Larger:
return CSSPixels(5) / 4;
default:
return 1;
} }
VERIFY_NOT_REACHED();
}
// https://drafts.csswg.org/css-fonts/#font-size-prop
CSSPixels StyleComputer::relative_size_mapping(RelativeSize relative_size, CSSPixels inherited_font_size)
{
// A <relative-size> keyword is interpreted relative to the computed font-size of the parent element and possibly
// the table of font sizes.
// If the parent element has a keyword font size in the absolute size keyword mapping table, larger may compute the
// font size to the next entry in the table, and smaller may compute the font size to the previous entry in the
// table. For example, if the parent element has a font size of font-size:medium, specifying a value of larger may
// make the font size of the child element font-size:large.
// Instead of using next and previous items in the previous keyword table, User agents may instead use a simple
// ratio to increase or decrease the font size relative to the parent element. The specific ratio is unspecified,
// but should be around 1.21.5. This ratio may vary across different elements.
switch (relative_size) {
case RelativeSize::Smaller:
return inherited_font_size * CSSPixels(4) / 5;
case RelativeSize::Larger:
return inherited_font_size * CSSPixels(5) / 4;
}
VERIFY_NOT_REACHED();
} }
RefPtr<Gfx::FontCascadeList const> StyleComputer::compute_font_for_style_values(Optional<DOM::AbstractElement> abstract_element, StyleValue const& font_family, StyleValue const& font_size, StyleValue const& font_style, StyleValue const& font_weight, StyleValue const& font_stretch, int math_depth) const RefPtr<Gfx::FontCascadeList const> StyleComputer::compute_font_for_style_values(Optional<DOM::AbstractElement> abstract_element, StyleValue const& font_family, StyleValue const& font_size, StyleValue const& font_style, StyleValue const& font_weight, StyleValue const& font_stretch, int math_depth) const
@ -1867,12 +1888,13 @@ RefPtr<Gfx::FontCascadeList const> StyleComputer::compute_font_for_style_values(
// TODO: If the parent element has a keyword font size in the absolute size keyword mapping table, // TODO: If the parent element has a keyword font size in the absolute size keyword mapping table,
// larger may compute the font size to the next entry in the table, // larger may compute the font size to the next entry in the table,
// and smaller may compute the font size to the previous entry in the table. // and smaller may compute the font size to the previous entry in the table.
if (keyword == Keyword::Smaller || keyword == Keyword::Larger) { if (auto relative_size = keyword_to_relative_size(keyword); relative_size.has_value()) {
if (parent_element.has_value() && parent_element->computed_properties()) { if (parent_element.has_value() && parent_element->computed_properties()) {
font_size_in_px = CSSPixels::nearest_value_for(parent_element->computed_properties()->first_available_computed_font().pixel_metrics().size); font_size_in_px = relative_size_mapping(relative_size.value(), parent_font_size);
} }
} else if (auto absolute_size = keyword_to_absolute_size(keyword); absolute_size.has_value()) {
font_size_in_px = absolute_size_mapping(absolute_size.value(), font_size_in_px);
} }
font_size_in_px *= absolute_size_mapping(keyword);
} }
} else { } else {
Length::ResolutionContext const length_resolution_context { Length::ResolutionContext const length_resolution_context {
@ -2504,8 +2526,18 @@ RefPtr<StyleValue const> StyleComputer::recascade_font_size_if_needed(DOM::Abstr
continue; continue;
} }
if (font_size_value->is_keyword()) { if (auto absolute_size = keyword_to_absolute_size(font_size_value->to_keyword()); absolute_size.has_value()) {
current_size_in_px = default_monospace_font_size_in_px * absolute_size_mapping(font_size_value->to_keyword()); current_size_in_px = absolute_size_mapping(absolute_size.value(), default_monospace_font_size_in_px);
continue;
}
if (auto relative_size = keyword_to_relative_size(font_size_value->to_keyword()); relative_size.has_value()) {
current_size_in_px = relative_size_mapping(relative_size.value(), current_size_in_px);
continue;
}
// FIXME: Resolve `font-size: math`
if (font_size_value->to_keyword() == Keyword::Math) {
continue; continue;
} }

View file

@ -175,7 +175,8 @@ public:
void unload_fonts_from_sheet(CSSStyleSheet&); void unload_fonts_from_sheet(CSSStyleSheet&);
static CSSPixels default_user_font_size(); static CSSPixels default_user_font_size();
static CSSPixelFraction absolute_size_mapping(Keyword); static CSSPixels absolute_size_mapping(AbsoluteSize, CSSPixels default_font_size);
static CSSPixels relative_size_mapping(RelativeSize, CSSPixels inherited_font_size);
RefPtr<Gfx::FontCascadeList const> compute_font_for_style_values(Optional<DOM::AbstractElement>, StyleValue const& font_family, StyleValue const& font_size, StyleValue const& font_style, StyleValue const& font_weight, StyleValue const& font_stretch, int math_depth = 0) const; RefPtr<Gfx::FontCascadeList const> compute_font_for_style_values(Optional<DOM::AbstractElement>, StyleValue const& font_family, StyleValue const& font_size, StyleValue const& font_style, StyleValue const& font_weight, StyleValue const& font_stretch, int math_depth = 0) const;
[[nodiscard]] RefPtr<StyleValue const> recascade_font_size_if_needed(DOM::AbstractElement, CascadedProperties&) const; [[nodiscard]] RefPtr<StyleValue const> recascade_font_size_if_needed(DOM::AbstractElement, CascadedProperties&) const;

View file

@ -4613,8 +4613,15 @@ CSSPixels font_size_to_pixel_size(Utf16View const& font_size)
if (!keyword.has_value()) if (!keyword.has_value())
return pixel_size; return pixel_size;
// Convert the keyword to an absolute-size
auto absolute_size = CSS::keyword_to_absolute_size(keyword.value());
// If that failed - give up
if (!absolute_size.has_value())
return pixel_size;
// Return scaled pixel size // Return scaled pixel size
return pixel_size * CSS::StyleComputer::absolute_size_mapping(keyword.release_value()); return CSS::StyleComputer::absolute_size_mapping(absolute_size.value(), pixel_size);
} }
void for_each_node_effectively_contained_in_range(GC::Ptr<DOM::Range> range, Function<TraversalDecision(GC::Ref<DOM::Node>)> callback) void for_each_node_effectively_contained_in_range(GC::Ptr<DOM::Range> range, Function<TraversalDecision(GC::Ref<DOM::Node>)> callback)