1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 19:37:34 +00:00

LibWeb: Add CSSPixels::nearest_value_for(FloatingPoint)

This is intended to annotate conversions from unknown floating-point
values to CSSPixels, and make it more obvious the fp value will be
rounded to the nearest fixed-point value.
This commit is contained in:
MacDue 2023-08-26 15:57:31 +01:00 committed by Alexander Kalenik
parent 360c0eb509
commit 71baa8c31a
28 changed files with 120 additions and 112 deletions

View file

@ -61,31 +61,31 @@ CSSPixels Length::font_relative_length_to_px(Length::FontMetrics const& font_met
{
switch (m_type) {
case Type::Em:
return CSSPixels(m_value * font_metrics.font_size.to_double());
return CSSPixels::nearest_value_for(m_value * font_metrics.font_size.to_double());
case Type::Rem:
return CSSPixels(m_value * root_font_metrics.font_size.to_double());
return CSSPixels::nearest_value_for(m_value * root_font_metrics.font_size.to_double());
case Type::Ex:
return CSSPixels(m_value * font_metrics.x_height.to_double());
return CSSPixels::nearest_value_for(m_value * font_metrics.x_height.to_double());
case Type::Rex:
return CSSPixels(m_value * root_font_metrics.x_height.to_double());
return CSSPixels::nearest_value_for(m_value * root_font_metrics.x_height.to_double());
case Type::Cap:
return CSSPixels(m_value * font_metrics.cap_height.to_double());
return CSSPixels::nearest_value_for(m_value * font_metrics.cap_height.to_double());
case Type::Rcap:
return CSSPixels(m_value * root_font_metrics.cap_height.to_double());
return CSSPixels::nearest_value_for(m_value * root_font_metrics.cap_height.to_double());
case Type::Ch:
return CSSPixels(m_value * font_metrics.zero_advance.to_double());
return CSSPixels::nearest_value_for(m_value * font_metrics.zero_advance.to_double());
case Type::Rch:
return CSSPixels(m_value * root_font_metrics.zero_advance.to_double());
return CSSPixels::nearest_value_for(m_value * root_font_metrics.zero_advance.to_double());
case Type::Ic:
// FIXME: Use the "advance measure of the “水” (CJK water ideograph, U+6C34) glyph"
return CSSPixels(m_value * font_metrics.font_size.to_double());
return CSSPixels::nearest_value_for(m_value * font_metrics.font_size.to_double());
case Type::Ric:
// FIXME: Use the "advance measure of the “水” (CJK water ideograph, U+6C34) glyph"
return CSSPixels(m_value * root_font_metrics.font_size.to_double());
return CSSPixels::nearest_value_for(m_value * root_font_metrics.font_size.to_double());
case Type::Lh:
return CSSPixels(m_value * font_metrics.line_height.to_double());
return CSSPixels::nearest_value_for(m_value * font_metrics.line_height.to_double());
case Type::Rlh:
return CSSPixels(m_value * root_font_metrics.line_height.to_double());
return CSSPixels::nearest_value_for(m_value * root_font_metrics.line_height.to_double());
default:
VERIFY_NOT_REACHED();
}
@ -98,34 +98,34 @@ CSSPixels Length::viewport_relative_length_to_px(CSSPixelRect const& viewport_re
case Type::Svw:
case Type::Lvw:
case Type::Dvw:
return CSSPixels(viewport_rect.width() * (m_value / 100));
return CSSPixels::nearest_value_for(viewport_rect.width() * (m_value / 100));
case Type::Vh:
case Type::Svh:
case Type::Lvh:
case Type::Dvh:
return CSSPixels(viewport_rect.height() * (m_value / 100));
return CSSPixels::nearest_value_for(viewport_rect.height() * (m_value / 100));
case Type::Vi:
case Type::Svi:
case Type::Lvi:
case Type::Dvi:
// FIXME: Select the width or height based on which is the inline axis.
return CSSPixels(viewport_rect.width() * (m_value / 100));
return CSSPixels::nearest_value_for(viewport_rect.width() * (m_value / 100));
case Type::Vb:
case Type::Svb:
case Type::Lvb:
case Type::Dvb:
// FIXME: Select the width or height based on which is the block axis.
return CSSPixels(viewport_rect.height() * (m_value / 100));
return CSSPixels::nearest_value_for(viewport_rect.height() * (m_value / 100));
case Type::Vmin:
case Type::Svmin:
case Type::Lvmin:
case Type::Dvmin:
return CSSPixels(min(viewport_rect.width(), viewport_rect.height()) * (m_value / 100));
return CSSPixels::nearest_value_for(min(viewport_rect.width(), viewport_rect.height()) * (m_value / 100));
case Type::Vmax:
case Type::Svmax:
case Type::Lvmax:
case Type::Dvmax:
return CSSPixels(max(viewport_rect.width(), viewport_rect.height()) * (m_value / 100));
return CSSPixels::nearest_value_for(max(viewport_rect.width(), viewport_rect.height()) * (m_value / 100));
default:
VERIFY_NOT_REACHED();
}
@ -138,8 +138,8 @@ Length::ResolutionContext Length::ResolutionContext::for_layout_node(Layout::Nod
VERIFY(root_element->layout_node());
return Length::ResolutionContext {
.viewport_rect = node.browsing_context().viewport_rect(),
.font_metrics = { CSSPixels(node.computed_values().font_size()), node.font().pixel_metrics(), node.line_height() },
.root_font_metrics = { CSSPixels(root_element->layout_node()->computed_values().font_size()), root_element->layout_node()->font().pixel_metrics(), root_element->layout_node()->line_height() },
.font_metrics = { CSSPixels::nearest_value_for(node.computed_values().font_size()), node.font().pixel_metrics(), node.line_height() },
.root_font_metrics = { CSSPixels::nearest_value_for(root_element->layout_node()->computed_values().font_size()), root_element->layout_node()->font().pixel_metrics(), root_element->layout_node()->line_height() },
};
}
@ -168,12 +168,12 @@ CSSPixels Length::to_px(Layout::Node const& layout_node) const
return 0;
FontMetrics font_metrics {
CSSPixels(layout_node.computed_values().font_size()),
CSSPixels::nearest_value_for(layout_node.computed_values().font_size()),
layout_node.font().pixel_metrics(),
layout_node.line_height()
};
FontMetrics root_font_metrics {
CSSPixels(root_element->layout_node()->computed_values().font_size()),
CSSPixels::nearest_value_for(root_element->layout_node()->computed_values().font_size()),
root_element->layout_node()->font().pixel_metrics(),
root_element->layout_node()->line_height()
};

View file

@ -185,19 +185,19 @@ public:
constexpr double centimeter_pixels = (inch_pixels / 2.54);
switch (m_type) {
case Type::Cm:
return CSSPixels(m_value * centimeter_pixels); // 1cm = 96px/2.54
return CSSPixels::nearest_value_for(m_value * centimeter_pixels); // 1cm = 96px/2.54
case Type::In:
return CSSPixels(m_value * inch_pixels); // 1in = 2.54 cm = 96px
return CSSPixels::nearest_value_for(m_value * inch_pixels); // 1in = 2.54 cm = 96px
case Type::Px:
return CSSPixels(m_value); // 1px = 1/96th of 1in
return CSSPixels::nearest_value_for(m_value); // 1px = 1/96th of 1in
case Type::Pt:
return CSSPixels(m_value * ((1.0 / 72.0) * inch_pixels)); // 1pt = 1/72th of 1in
return CSSPixels::nearest_value_for(m_value * ((1.0 / 72.0) * inch_pixels)); // 1pt = 1/72th of 1in
case Type::Pc:
return CSSPixels(m_value * ((1.0 / 6.0) * inch_pixels)); // 1pc = 1/6th of 1in
return CSSPixels::nearest_value_for(m_value * ((1.0 / 6.0) * inch_pixels)); // 1pc = 1/6th of 1in
case Type::Mm:
return CSSPixels(m_value * ((1.0 / 10.0) * centimeter_pixels)); // 1mm = 1/10th of 1cm
return CSSPixels::nearest_value_for(m_value * ((1.0 / 10.0) * centimeter_pixels)); // 1mm = 1/10th of 1cm
case Type::Q:
return CSSPixels(m_value * ((1.0 / 40.0) * centimeter_pixels)); // 1Q = 1/40th of 1cm
return CSSPixels::nearest_value_for(m_value * ((1.0 / 40.0) * centimeter_pixels)); // 1Q = 1/40th of 1cm
default:
VERIFY_NOT_REACHED();
}

View file

@ -168,7 +168,7 @@ bool MediaFeature::compare(HTML::Window const& window, MediaFeatureValue left, C
auto const& initial_font = window.associated_document().style_computer().initial_font();
Gfx::FontPixelMetrics const& initial_font_metrics = initial_font.pixel_metrics();
Length::FontMetrics font_metrics { CSSPixels(initial_font.presentation_size()), initial_font_metrics, CSSPixels(initial_font_metrics.line_spacing()) };
Length::FontMetrics font_metrics { initial_font.presentation_size(), initial_font_metrics, CSSPixels::nearest_value_for(initial_font_metrics.line_spacing()) };
left_px = left.length().to_px(viewport_rect, font_metrics, font_metrics);
right_px = right.length().to_px(viewport_rect, font_metrics, font_metrics);

View file

@ -1787,7 +1787,7 @@ Optional<Dimension> Parser::parse_dimension(ComponentValue const& component_valu
// FIXME: Disallow quirk when inside a CSS sub-expression (like `calc()`)
// "The <quirky-length> value must not be supported in arguments to CSS expressions other than the rect()
// expression, and must not be supported in the supports() static method of the CSS interface."
return Length::make_px(CSSPixels(numeric_value));
return Length::make_px(CSSPixels::nearest_value_for(numeric_value));
}
}

View file

@ -596,7 +596,7 @@ RefPtr<StyleValue const> ResolvedCSSStyleDeclaration::style_value_for_property(L
case PropertyID::Float:
return IdentifierStyleValue::create(to_value_id(layout_node.computed_values().float_()));
case PropertyID::FontSize:
return LengthStyleValue::create(Length::make_px(CSSPixels(layout_node.computed_values().font_size())));
return LengthStyleValue::create(Length::make_px(CSSPixels::nearest_value_for(layout_node.computed_values().font_size())));
case PropertyID::FontVariant: {
auto font_variant = layout_node.computed_values().font_variant();
switch (font_variant) {

View file

@ -2036,7 +2036,7 @@ Length::FontMetrics StyleComputer::calculate_root_element_font_metrics(StyleProp
auto root_value = style.property(CSS::PropertyID::FontSize);
auto font_pixel_metrics = style.computed_font().pixel_metrics();
Length::FontMetrics font_metrics { m_default_font_metrics.font_size, font_pixel_metrics, CSSPixels(font_pixel_metrics.line_spacing()) };
Length::FontMetrics font_metrics { m_default_font_metrics.font_size, font_pixel_metrics, CSSPixels::nearest_value_for(font_pixel_metrics.line_spacing()) };
font_metrics.font_size = root_value->as_length().length().to_px(viewport_rect(), font_metrics, font_metrics);
font_metrics.line_height = style.line_height(viewport_rect(), font_metrics, font_metrics);
@ -2197,7 +2197,7 @@ RefPtr<Gfx::Font const> StyleComputer::compute_font_for_style_values(DOM::Elemen
// 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(parent_element->computed_css_values()->computed_font().pixel_metrics().size);
font_size_in_px = CSSPixels::nearest_value_for(parent_element->computed_css_values()->computed_font().pixel_metrics().size);
}
}
auto const multiplier = absolute_size_mapping.get(identifier).value_or(1.0);
@ -2213,7 +2213,7 @@ RefPtr<Gfx::Font const> StyleComputer::compute_font_for_style_values(DOM::Elemen
Optional<Length> maybe_length;
if (font_size.is_percentage()) {
// Percentages refer to parent element's font size
maybe_length = Length::make_px(CSSPixels(font_size.as_percentage().percentage().as_fraction() * parent_font_size().to_double()));
maybe_length = Length::make_px(CSSPixels::nearest_value_for(font_size.as_percentage().percentage().as_fraction() * parent_font_size().to_double()));
} else if (font_size.is_length()) {
maybe_length = font_size.as_length().length();
@ -2350,7 +2350,7 @@ void StyleComputer::compute_font(StyleProperties& style, DOM::Element const* ele
auto found_font = compute_font_for_style_values(element, pseudo_element, font_family, font_size, font_style, font_weight, font_stretch);
style.set_property(CSS::PropertyID::FontSize, LengthStyleValue::create(CSS::Length::make_px(CSSPixels(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_computed_font(found_font.release_nonnull());
@ -2401,7 +2401,7 @@ void StyleComputer::absolutize_values(StyleProperties& style, DOM::Element const
auto line_height_value_slot = style.m_property_values[to_underlying(CSS::PropertyID::LineHeight)].map([](auto& x) -> auto& { return x.style; });
if (line_height_value_slot.has_value() && (*line_height_value_slot)->is_percentage()) {
*line_height_value_slot = LengthStyleValue::create(
Length::make_px(CSSPixels(font_size * static_cast<double>((*line_height_value_slot)->as_percentage().percentage().as_fraction()))));
Length::make_px(CSSPixels::nearest_value_for(font_size * static_cast<double>((*line_height_value_slot)->as_percentage().percentage().as_fraction()))));
}
auto line_height = style.line_height(viewport_rect(), font_metrics, m_root_element_font_metrics);

View file

@ -204,7 +204,7 @@ CSSPixels StyleProperties::line_height(Layout::Node const& layout_node) const
auto line_height = property(CSS::PropertyID::LineHeight);
if (line_height->is_identifier() && line_height->to_identifier() == ValueID::Normal)
return CSSPixels(layout_node.font().pixel_metrics().line_spacing());
return CSSPixels::nearest_value_for(layout_node.font().pixel_metrics().line_spacing());
if (line_height->is_length()) {
auto line_height_length = line_height->as_length().length();
@ -226,7 +226,7 @@ CSSPixels StyleProperties::line_height(Layout::Node const& layout_node) const
auto resolved = line_height->as_calculated().resolve_number();
if (!resolved.has_value()) {
dbgln("FIXME: Failed to resolve calc() line-height (number): {}", line_height->as_calculated().to_string());
return CSSPixels(layout_node.font().pixel_metrics().line_spacing());
return CSSPixels::nearest_value_for(layout_node.font().pixel_metrics().line_spacing());
}
return Length(resolved.value(), Length::Type::Em).to_px(layout_node);
}
@ -234,12 +234,12 @@ CSSPixels StyleProperties::line_height(Layout::Node const& layout_node) const
auto resolved = line_height->as_calculated().resolve_length(layout_node);
if (!resolved.has_value()) {
dbgln("FIXME: Failed to resolve calc() line-height: {}", line_height->as_calculated().to_string());
return CSSPixels(layout_node.font().pixel_metrics().line_spacing());
return CSSPixels::nearest_value_for(layout_node.font().pixel_metrics().line_spacing());
}
return resolved->to_px(layout_node);
}
return CSSPixels(layout_node.font().pixel_metrics().line_spacing());
return CSSPixels::nearest_value_for(layout_node.font().pixel_metrics().line_spacing());
}
Optional<int> StyleProperties::z_index() const

View file

@ -77,7 +77,7 @@ static CalculatedStyleValue::CalculationResult to_resolved_type(CalculatedStyleV
case CalculatedStyleValue::ResolvedType::Frequency:
return { Frequency::make_hertz(value) };
case CalculatedStyleValue::ResolvedType::Length:
return { Length::make_px(CSSPixels(value)) };
return { Length::make_px(CSSPixels::nearest_value_for(value)) };
case CalculatedStyleValue::ResolvedType::Percentage:
return { Percentage(value) };
case CalculatedStyleValue::ResolvedType::Time:
@ -2155,7 +2155,7 @@ void CalculatedStyleValue::CalculationResult::multiply_by(CalculationResult cons
m_value = Frequency::make_hertz(frequency.to_hertz() * other.m_value.get<Number>().value());
},
[&](Length const& length) {
m_value = Length::make_px(CSSPixels(length.to_px(*context) * static_cast<double>(other.m_value.get<Number>().value())));
m_value = Length::make_px(CSSPixels::nearest_value_for(length.to_px(*context) * static_cast<double>(other.m_value.get<Number>().value())));
},
[&](Time const& time) {
m_value = Time::make_seconds(time.to_seconds() * other.m_value.get<Number>().value());
@ -2187,7 +2187,7 @@ void CalculatedStyleValue::CalculationResult::divide_by(CalculationResult const&
m_value = Frequency::make_hertz(frequency.to_hertz() / denominator);
},
[&](Length const& length) {
m_value = Length::make_px(CSSPixels(length.to_px(*context) / static_cast<double>(denominator)));
m_value = Length::make_px(CSSPixels::nearest_value_for(length.to_px(*context) / static_cast<double>(denominator)));
},
[&](Time const& time) {
m_value = Time::make_seconds(time.to_seconds() / denominator);

View file

@ -150,8 +150,8 @@ Gfx::FloatSize RadialGradientStyleValue::resolve_size(Layout::Node const& node,
return Gfx::FloatSize { radius.to_float(), radius.to_float() };
},
[&](EllipseSize const& ellipse_size) {
auto radius_a = ellipse_size.radius_a.resolved(node, CSS::Length::make_px(CSSPixels(size.width()))).to_px(node);
auto radius_b = ellipse_size.radius_b.resolved(node, CSS::Length::make_px(CSSPixels(size.height()))).to_px(node);
auto radius_a = ellipse_size.radius_a.resolved(node, CSS::Length::make_px(CSSPixels::nearest_value_for(size.width()))).to_px(node);
auto radius_b = ellipse_size.radius_b.resolved(node, CSS::Length::make_px(CSSPixels::nearest_value_for(size.height()))).to_px(node);
return Gfx::FloatSize { radius_a.to_float(), radius_b.to_float() };
});