mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 16:47:36 +00:00
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
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",
|
"x-small",
|
||||||
"xx-large",
|
"xx-large",
|
||||||
"xx-small",
|
"xx-small",
|
||||||
"xxx-large"
|
"xxx-large",
|
||||||
|
"math"
|
||||||
],
|
],
|
||||||
"percentages-resolve-to": "length",
|
"percentages-resolve-to": "length",
|
||||||
"quirks": [
|
"quirks": [
|
||||||
|
|
|
@ -1907,7 +1907,7 @@ RefPtr<Gfx::Font const> StyleComputer::font_matching_algorithm(FontFaceKey const
|
||||||
return {};
|
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);
|
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();
|
auto const identifier = static_cast<IdentifierStyleValue const&>(font_size).id();
|
||||||
|
|
||||||
// https://w3c.github.io/csswg-drafts/css-fonts/#valdef-font-size-relative-size
|
if (identifier == ValueID::Math) {
|
||||||
// TODO: If the parent element has a keyword font size in the absolute size keyword mapping table,
|
auto math_scaling_factor = [&]() {
|
||||||
// larger may compute the font size to the next entry in the table,
|
// https://w3c.github.io/mathml-core/#the-math-script-level-property
|
||||||
// and smaller may compute the font size to the previous entry in the table.
|
// If the specified value font-size is math then the computed value of font-size is obtained by multiplying
|
||||||
if (identifier == CSS::ValueID::Smaller || identifier == CSS::ValueID::Larger) {
|
// the inherited value of font-size by a nonzero scale factor calculated by the following procedure:
|
||||||
if (parent_element && parent_element->computed_css_values()) {
|
// 1. Let A be the inherited math-depth value, B the computed math-depth value, C be 0.71 and S be 1.0
|
||||||
font_size_in_px = CSSPixels::nearest_value_for(parent_element->computed_css_values()->computed_font().pixel_metrics().size);
|
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 {
|
} else {
|
||||||
Length::ResolutionContext const length_resolution_context {
|
Length::ResolutionContext const length_resolution_context {
|
||||||
.viewport_rect = viewport_rect(),
|
.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_weight = style.property(CSS::PropertyID::FontWeight);
|
||||||
auto font_stretch = style.property(CSS::PropertyID::FontStretch);
|
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::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()));
|
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&);
|
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 {
|
struct AnimationKey {
|
||||||
CSS::CSSStyleDeclaration const* source_declaration;
|
CSS::CSSStyleDeclaration const* source_declaration;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue