LibWeb: Implement font-size: math
This is a MathML extension, basically a big hack to make parts of equations smaller, such as sub/superscripts. The important thing is, it works. :^)
This commit is contained in:
parent
6476dea898
commit
f7209fb9d4
Notes:
sideshowbarker
2024-07-16 19:57:55 +09:00
Author: https://github.com/AtkinsSJ Commit: https://github.com/SerenityOS/serenity/commit/f7209fb9d4 Pull-request: https://github.com/SerenityOS/serenity/pull/20985
5 changed files with 104 additions and 12 deletions
39
Tests/LibWeb/Layout/expected/css-font-size-math.txt
Normal file
39
Tests/LibWeb/Layout/expected/css-font-size-math.txt
Normal file
|
@ -0,0 +1,39 @@
|
|||
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
||||
BlockContainer <html> at (0,0) content-size 800x600 [BFC] children: not-inline
|
||||
BlockContainer <body> at (8,8) content-size 784x78.609375 children: inline
|
||||
line 0 width: 78.9375, height: 78.609375, bottom: 78.609375, baseline: 60.90625
|
||||
frag 0 from TextNode start: 0, length: 1, rect: [8,25 39.09375x55.8125]
|
||||
"H"
|
||||
frag 1 from TextNode start: 0, length: 1, rect: [47,38 19.78125x39.625]
|
||||
"e"
|
||||
frag 2 from TextNode start: 0, length: 1, rect: [67,47 6.8125x28.125]
|
||||
"l"
|
||||
frag 3 from TextNode start: 0, length: 1, rect: [74,53 4.84375x19.96875]
|
||||
"l"
|
||||
frag 4 from TextNode start: 0, length: 1, rect: [79,57 8.40625x14.171875]
|
||||
"o"
|
||||
InlineNode <span>
|
||||
TextNode <#text>
|
||||
InlineNode <span>
|
||||
TextNode <#text>
|
||||
InlineNode <span>
|
||||
TextNode <#text>
|
||||
InlineNode <span>
|
||||
TextNode <#text>
|
||||
InlineNode <span>
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
|
||||
ViewportPaintable (Viewport<#document>) [0,0 800x600]
|
||||
PaintableWithLines (BlockContainer<HTML>) [0,0 800x600]
|
||||
PaintableWithLines (BlockContainer<BODY>) [8,8 784x78.609375]
|
||||
InlinePaintable (InlineNode<SPAN>)
|
||||
TextPaintable (TextNode<#text>)
|
||||
InlinePaintable (InlineNode<SPAN>)
|
||||
TextPaintable (TextNode<#text>)
|
||||
InlinePaintable (InlineNode<SPAN>)
|
||||
TextPaintable (TextNode<#text>)
|
||||
InlinePaintable (InlineNode<SPAN>)
|
||||
TextPaintable (TextNode<#text>)
|
||||
InlinePaintable (InlineNode<SPAN>)
|
||||
TextPaintable (TextNode<#text>)
|
10
Tests/LibWeb/Layout/input/css-font-size-math.html
Normal file
10
Tests/LibWeb/Layout/input/css-font-size-math.html
Normal file
|
@ -0,0 +1,10 @@
|
|||
<style>
|
||||
body {
|
||||
font: 72px SerenitySans;
|
||||
}
|
||||
span {
|
||||
font-size: math;
|
||||
math-depth: add(1);
|
||||
}
|
||||
</style>
|
||||
<span>H<span>e<span>l<span>l<span>o</span></span></span></span></span>
|
|
@ -864,7 +864,8 @@
|
|||
"x-small",
|
||||
"xx-large",
|
||||
"xx-small",
|
||||
"xxx-large"
|
||||
"xxx-large",
|
||||
"math"
|
||||
],
|
||||
"percentages-resolve-to": "length",
|
||||
"quirks": [
|
||||
|
|
|
@ -1907,7 +1907,7 @@ RefPtr<Gfx::Font const> StyleComputer::font_matching_algorithm(FontFaceKey const
|
|||
return {};
|
||||
}
|
||||
|
||||
RefPtr<Gfx::Font const> StyleComputer::compute_font_for_style_values(DOM::Element const* element, Optional<CSS::Selector::PseudoElement> pseudo_element, StyleValue const& font_family, StyleValue const& font_size, StyleValue const& font_style, StyleValue const& font_weight, StyleValue const& font_stretch) const
|
||||
RefPtr<Gfx::Font const> StyleComputer::compute_font_for_style_values(DOM::Element const* element, Optional<CSS::Selector::PseudoElement> pseudo_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
|
||||
{
|
||||
auto* parent_element = element_to_inherit_style_from(element, pseudo_element);
|
||||
|
||||
|
@ -1972,16 +1972,58 @@ RefPtr<Gfx::Font const> StyleComputer::compute_font_for_style_values(DOM::Elemen
|
|||
|
||||
auto const identifier = static_cast<IdentifierStyleValue const&>(font_size).id();
|
||||
|
||||
// https://w3c.github.io/csswg-drafts/css-fonts/#valdef-font-size-relative-size
|
||||
// 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,
|
||||
// and smaller may compute the font size to the previous entry in the table.
|
||||
if (identifier == CSS::ValueID::Smaller || identifier == CSS::ValueID::Larger) {
|
||||
if (parent_element && parent_element->computed_css_values()) {
|
||||
font_size_in_px = CSSPixels::nearest_value_for(parent_element->computed_css_values()->computed_font().pixel_metrics().size);
|
||||
if (identifier == ValueID::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
|
||||
// the inherited value of font-size by a nonzero scale factor calculated by the following procedure:
|
||||
// 1. Let A be the inherited math-depth value, B the computed math-depth value, C be 0.71 and S be 1.0
|
||||
int inherited_math_depth = parent_element && parent_element->computed_css_values()
|
||||
? parent_element->computed_css_values()->math_depth()
|
||||
: InitialValues::math_depth();
|
||||
int computed_math_depth = math_depth;
|
||||
auto size_ratio = 0.71;
|
||||
auto scale = 1.0;
|
||||
// 2. If A = B then return S.
|
||||
bool invert_scale_factor = false;
|
||||
if (inherited_math_depth == computed_math_depth) {
|
||||
return scale;
|
||||
}
|
||||
// If B < A, swap A and B and set InvertScaleFactor to true.
|
||||
else if (computed_math_depth < inherited_math_depth) {
|
||||
AK::swap(inherited_math_depth, computed_math_depth);
|
||||
invert_scale_factor = true;
|
||||
}
|
||||
// Otherwise B > A and set InvertScaleFactor to false.
|
||||
else {
|
||||
invert_scale_factor = false;
|
||||
}
|
||||
// 3. Let E be B - A > 0.
|
||||
double e = (computed_math_depth - inherited_math_depth) > 0;
|
||||
// FIXME: 4. If the inherited first available font has an OpenType MATH table:
|
||||
// - If A ≤ 0 and B ≥ 2 then multiply S by scriptScriptPercentScaleDown and decrement E by 2.
|
||||
// - Otherwise if A = 1 then multiply S by scriptScriptPercentScaleDown / scriptPercentScaleDown and decrement E by 1.
|
||||
// - Otherwise if B = 1 then multiply S by scriptPercentScaleDown and decrement E by 1.
|
||||
// 5. Multiply S by C^E.
|
||||
scale *= AK::pow(size_ratio, e);
|
||||
// 6. Return S if InvertScaleFactor is false and 1/S otherwise.
|
||||
if (!invert_scale_factor)
|
||||
return scale;
|
||||
return 1.0 / scale;
|
||||
};
|
||||
font_size_in_px = parent_font_size().scale_by(math_scaling_factor());
|
||||
} else {
|
||||
// https://w3c.github.io/csswg-drafts/css-fonts/#valdef-font-size-relative-size
|
||||
// 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,
|
||||
// and smaller may compute the font size to the previous entry in the table.
|
||||
if (identifier == CSS::ValueID::Smaller || identifier == CSS::ValueID::Larger) {
|
||||
if (parent_element && parent_element->computed_css_values()) {
|
||||
font_size_in_px = CSSPixels::nearest_value_for(parent_element->computed_css_values()->computed_font().pixel_metrics().size);
|
||||
}
|
||||
}
|
||||
font_size_in_px *= get_absolute_size_mapping(identifier);
|
||||
}
|
||||
font_size_in_px *= get_absolute_size_mapping(identifier);
|
||||
} else {
|
||||
Length::ResolutionContext const length_resolution_context {
|
||||
.viewport_rect = viewport_rect(),
|
||||
|
@ -2126,7 +2168,7 @@ void StyleComputer::compute_font(StyleProperties& style, DOM::Element const* ele
|
|||
auto font_weight = style.property(CSS::PropertyID::FontWeight);
|
||||
auto font_stretch = style.property(CSS::PropertyID::FontStretch);
|
||||
|
||||
auto found_font = compute_font_for_style_values(element, pseudo_element, font_family, font_size, font_style, font_weight, font_stretch);
|
||||
auto found_font = compute_font_for_style_values(element, pseudo_element, font_family, font_size, font_style, font_weight, font_stretch, style.math_depth());
|
||||
|
||||
style.set_property(CSS::PropertyID::FontSize, LengthStyleValue::create(CSS::Length::make_px(CSSPixels::nearest_value_for(found_font->pixel_size()))), nullptr);
|
||||
style.set_property(CSS::PropertyID::FontWeight, NumberStyleValue::create(font_weight->to_font_weight()));
|
||||
|
|
|
@ -74,7 +74,7 @@ public:
|
|||
|
||||
void load_fonts_from_sheet(CSSStyleSheet const&);
|
||||
|
||||
RefPtr<Gfx::Font const> compute_font_for_style_values(DOM::Element const* element, Optional<CSS::Selector::PseudoElement> pseudo_element, StyleValue const& font_family, StyleValue const& font_size, StyleValue const& font_style, StyleValue const& font_weight, StyleValue const& font_stretch) const;
|
||||
RefPtr<Gfx::Font const> compute_font_for_style_values(DOM::Element const* element, Optional<CSS::Selector::PseudoElement> pseudo_element, 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;
|
||||
|
||||
struct AnimationKey {
|
||||
CSS::CSSStyleDeclaration const* source_declaration;
|
||||
|
|
Loading…
Add table
Reference in a new issue