mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 21:27:35 +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:
parent
360c0eb509
commit
71baa8c31a
28 changed files with 120 additions and 112 deletions
|
@ -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()
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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() };
|
||||
});
|
||||
|
||||
|
|
|
@ -1085,7 +1085,7 @@ void Element::set_scroll_left(double x)
|
|||
// 11. Scroll the element to x,scrollTop, with the scroll behavior being "auto".
|
||||
// FIXME: Implement this in terms of calling "scroll the element".
|
||||
auto scroll_offset = paintable_box()->scroll_offset();
|
||||
scroll_offset.set_x(CSSPixels(x));
|
||||
scroll_offset.set_x(CSSPixels::nearest_value_for(x));
|
||||
paintable_box()->set_scroll_offset(scroll_offset);
|
||||
}
|
||||
|
||||
|
@ -1153,7 +1153,7 @@ void Element::set_scroll_top(double y)
|
|||
// 11. Scroll the element to scrollLeft,y, with the scroll behavior being "auto".
|
||||
// FIXME: Implement this in terms of calling "scroll the element".
|
||||
auto scroll_offset = paintable_box()->scroll_offset();
|
||||
scroll_offset.set_y(CSSPixels(y));
|
||||
scroll_offset.set_y(CSSPixels::nearest_value_for(y));
|
||||
paintable_box()->set_scroll_offset(scroll_offset);
|
||||
}
|
||||
|
||||
|
|
|
@ -3993,14 +3993,14 @@ static RefPtr<CSS::StyleValue> parse_current_dimension_value(float value, Utf8Vi
|
|||
{
|
||||
// 1. If position is past the end of input, then return value as a length.
|
||||
if (position == input.end())
|
||||
return CSS::LengthStyleValue::create(CSS::Length::make_px(CSSPixels(value)));
|
||||
return CSS::LengthStyleValue::create(CSS::Length::make_px(CSSPixels::nearest_value_for(value)));
|
||||
|
||||
// 2. If the code point at position within input is U+0025 (%), then return value as a percentage.
|
||||
if (*position == '%')
|
||||
return CSS::PercentageStyleValue::create(CSS::Percentage(value));
|
||||
|
||||
// 3. Return value as a length.
|
||||
return CSS::LengthStyleValue::create(CSS::Length::make_px(CSSPixels(value)));
|
||||
return CSS::LengthStyleValue::create(CSS::Length::make_px(CSSPixels::nearest_value_for(value)));
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#rules-for-parsing-dimension-values
|
||||
|
@ -4065,7 +4065,7 @@ RefPtr<CSS::StyleValue> parse_dimension_value(StringView string)
|
|||
|
||||
// 4. If position is past the end of input, then return value as a length.
|
||||
if (position == input.end())
|
||||
return CSS::LengthStyleValue::create(CSS::Length::make_px(CSSPixels(value)));
|
||||
return CSS::LengthStyleValue::create(CSS::Length::make_px(CSSPixels::nearest_value_for(value)));
|
||||
|
||||
// 5. If the code point at position within input is not an ASCII digit, then break.
|
||||
if (!is_ascii_digit(*position))
|
||||
|
|
|
@ -1069,7 +1069,7 @@ void BlockFormattingContext::layout_list_item_marker(ListItemBox const& list_ite
|
|||
marker_state.set_content_width(image_width + default_marker_width);
|
||||
} else {
|
||||
auto text_width = marker.font().width(marker.text());
|
||||
marker_state.set_content_width(image_width + CSSPixels(text_width));
|
||||
marker_state.set_content_width(image_width + CSSPixels::nearest_value_for(text_width));
|
||||
}
|
||||
|
||||
marker_state.set_content_height(max(image_height, marker.font().pixel_size_rounded_up() + 1));
|
||||
|
@ -1084,7 +1084,7 @@ void BlockFormattingContext::layout_list_item_marker(ListItemBox const& list_ite
|
|||
list_item_state.set_content_width(list_item_state.content_width() - final_marker_width);
|
||||
}
|
||||
|
||||
auto offset_y = max(CSSPixels(0), (CSSPixels(marker.line_height()) - marker_state.content_height()) / 2);
|
||||
auto offset_y = max(CSSPixels(0), (marker.line_height() - marker_state.content_height()) / 2);
|
||||
auto space_and_containing_margin = intrusion_by_floats_into_box(list_item_box, offset_y);
|
||||
marker_state.set_content_offset({ space_and_containing_margin.left - final_marker_width, offset_y });
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ void ButtonBox::prepare_for_replaced_layout()
|
|||
// value attribute. This is not the case with <button />, which contains
|
||||
// its contents normally.
|
||||
if (is<HTML::HTMLInputElement>(dom_node())) {
|
||||
set_natural_width(CSSPixels(font().width(static_cast<HTML::HTMLInputElement&>(dom_node()).value())));
|
||||
set_natural_width(CSSPixels::nearest_value_for(font().width(static_cast<HTML::HTMLInputElement&>(dom_node()).value())));
|
||||
set_natural_height(font().pixel_size_rounded_up());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -540,15 +540,15 @@ CSS::FlexBasis FlexFormattingContext::used_flex_basis_for_item(FlexItem const& i
|
|||
CSSPixels FlexFormattingContext::calculate_main_size_from_cross_size_and_aspect_ratio(CSSPixels cross_size, double aspect_ratio) const
|
||||
{
|
||||
if (is_row_layout())
|
||||
return CSSPixels(cross_size * aspect_ratio);
|
||||
return CSSPixels(cross_size / aspect_ratio);
|
||||
return CSSPixels::nearest_value_for(cross_size * aspect_ratio);
|
||||
return CSSPixels::nearest_value_for(cross_size / aspect_ratio);
|
||||
}
|
||||
|
||||
CSSPixels FlexFormattingContext::calculate_cross_size_from_main_size_and_aspect_ratio(CSSPixels main_size, double aspect_ratio) const
|
||||
{
|
||||
if (is_row_layout())
|
||||
return CSSPixels(main_size / aspect_ratio);
|
||||
return CSSPixels(main_size * aspect_ratio);
|
||||
return CSSPixels::nearest_value_for(main_size / aspect_ratio);
|
||||
return CSSPixels::nearest_value_for(main_size * aspect_ratio);
|
||||
}
|
||||
|
||||
// This function takes a size in the main axis and adjusts it according to the aspect ratio of the box
|
||||
|
@ -982,7 +982,7 @@ void FlexFormattingContext::resolve_flexible_lengths_for_line(FlexLine& line)
|
|||
|
||||
// If the sum of the unfrozen flex items’ flex factors is less than one, multiply the initial free space by this sum.
|
||||
if (auto sum_of_flex_factor_of_unfrozen_items = line.sum_of_flex_factor_of_unfrozen_items(); sum_of_flex_factor_of_unfrozen_items < 1 && initial_free_space.has_value()) {
|
||||
auto value = CSSPixels(initial_free_space.value() * sum_of_flex_factor_of_unfrozen_items);
|
||||
auto value = CSSPixels::nearest_value_for(initial_free_space.value() * sum_of_flex_factor_of_unfrozen_items);
|
||||
// If the magnitude of this value is less than the magnitude of the remaining free space, use this as the remaining free space.
|
||||
if (abs(value) < abs(line.remaining_free_space.value()))
|
||||
line.remaining_free_space = value;
|
||||
|
@ -1793,7 +1793,7 @@ CSSPixels FlexFormattingContext::calculate_intrinsic_main_size_of_flex_container
|
|||
product = flex_line.chosen_flex_fraction * static_cast<double>(item.box->computed_values().flex_grow());
|
||||
else if (item.desired_flex_fraction < 0)
|
||||
product = flex_line.chosen_flex_fraction * item.scaled_flex_shrink_factor;
|
||||
auto result = item.flex_base_size + CSSPixels(product);
|
||||
auto result = item.flex_base_size + CSSPixels::nearest_value_for(product);
|
||||
|
||||
auto const& computed_min_size = this->computed_main_min_size(item.box);
|
||||
auto const& computed_max_size = this->computed_main_max_size(item.box);
|
||||
|
|
|
@ -500,7 +500,7 @@ CSSPixels FormattingContext::tentative_height_for_replaced_element(Box const& bo
|
|||
//
|
||||
// (used width) / (intrinsic ratio)
|
||||
if (computed_height.is_auto() && box.has_preferred_aspect_ratio())
|
||||
return CSSPixels(m_state.get(box).content_width() / static_cast<double>(box.preferred_aspect_ratio().value()));
|
||||
return CSSPixels::nearest_value_for(m_state.get(box).content_width() / static_cast<double>(box.preferred_aspect_ratio().value()));
|
||||
|
||||
// Otherwise, if 'height' has a computed value of 'auto', and the element has an intrinsic height, then that intrinsic height is the used value of 'height'.
|
||||
if (computed_height.is_auto() && box.has_natural_height())
|
||||
|
@ -1403,7 +1403,7 @@ CSSPixels FormattingContext::calculate_min_content_height(Layout::Box const& box
|
|||
CSSPixels FormattingContext::calculate_max_content_height(Layout::Box const& box, CSSPixels width) const
|
||||
{
|
||||
if (box.has_preferred_aspect_ratio())
|
||||
return CSSPixels(width / static_cast<double>(*box.preferred_aspect_ratio()));
|
||||
return CSSPixels::nearest_value_for(width / static_cast<double>(*box.preferred_aspect_ratio()));
|
||||
|
||||
if (box.has_natural_height())
|
||||
return *box.natural_height();
|
||||
|
@ -1711,10 +1711,10 @@ CSSPixels FormattingContext::box_baseline(Box const& box) const
|
|||
return box_state.content_height() + box_state.margin_box_top();
|
||||
case CSS::VerticalAlign::TextTop:
|
||||
// TextTop: Align the top of the box with the top of the parent's content area (see 10.6.1).
|
||||
return CSSPixels(box.computed_values().font_size());
|
||||
return CSSPixels::nearest_value_for(box.computed_values().font_size());
|
||||
case CSS::VerticalAlign::TextBottom:
|
||||
// TextTop: Align the bottom of the box with the bottom of the parent's content area (see 10.6.1).
|
||||
return box_state.content_height() - CSSPixels(box.containing_block()->font().pixel_metrics().descent * 2);
|
||||
return box_state.content_height() - CSSPixels::nearest_value_for(box.containing_block()->font().pixel_metrics().descent * 2);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1245,7 +1245,7 @@ void GridFormattingContext::expand_flexible_tracks(AvailableSpace const& availab
|
|||
for (auto& track : tracks) {
|
||||
if (track.max_track_sizing_function.is_flexible_length()) {
|
||||
if (track.max_track_sizing_function.flex_factor() > 1) {
|
||||
result = max(result, CSSPixels(track.base_size / track.max_track_sizing_function.flex_factor()));
|
||||
result = max(result, CSSPixels::nearest_value_for(track.base_size / track.max_track_sizing_function.flex_factor()));
|
||||
} else {
|
||||
result = max(result, track.base_size);
|
||||
}
|
||||
|
|
|
@ -34,11 +34,11 @@ void ImageBox::prepare_for_replaced_layout()
|
|||
|
||||
CSSPixels alt_text_width = 0;
|
||||
if (!m_cached_alt_text_width.has_value())
|
||||
m_cached_alt_text_width = CSSPixels(font.width(alt));
|
||||
m_cached_alt_text_width = CSSPixels::nearest_value_for(font.width(alt));
|
||||
alt_text_width = m_cached_alt_text_width.value();
|
||||
|
||||
set_natural_width(alt_text_width + 16);
|
||||
set_natural_height(CSSPixels(font.pixel_size()) + 16);
|
||||
set_natural_height(CSSPixels::nearest_value_for(font.pixel_size()) + 16);
|
||||
}
|
||||
|
||||
if (!has_natural_width() && !has_natural_height()) {
|
||||
|
|
|
@ -180,7 +180,7 @@ Optional<InlineLevelIterator::Item> InlineLevelIterator::next_without_lookahead(
|
|||
m_text_node_context->is_last_chunk = true;
|
||||
|
||||
auto& chunk = chunk_opt.value();
|
||||
CSSPixels chunk_width = CSSPixels(text_node.font().width(chunk.view) + text_node.font().glyph_spacing());
|
||||
CSSPixels chunk_width = CSSPixels::nearest_value_for(text_node.font().width(chunk.view) + text_node.font().glyph_spacing());
|
||||
|
||||
if (m_text_node_context->do_respect_linebreaks && chunk.has_breaking_newline) {
|
||||
return Item {
|
||||
|
|
|
@ -51,7 +51,7 @@ int LineBoxFragment::text_index_at(CSSPixels x) const
|
|||
Utf8View view(text());
|
||||
|
||||
CSSPixels relative_x = x - absolute_x();
|
||||
CSSPixels glyph_spacing = CSSPixels(font.glyph_spacing());
|
||||
CSSPixels glyph_spacing = font.glyph_spacing();
|
||||
|
||||
if (relative_x < 0)
|
||||
return 0;
|
||||
|
@ -59,7 +59,7 @@ int LineBoxFragment::text_index_at(CSSPixels x) const
|
|||
CSSPixels width_so_far = 0;
|
||||
for (auto it = view.begin(); it != view.end(); ++it) {
|
||||
auto previous_it = it;
|
||||
CSSPixels glyph_width = CSSPixels(font.glyph_or_emoji_width(it));
|
||||
CSSPixels glyph_width = CSSPixels::nearest_value_for(font.glyph_or_emoji_width(it));
|
||||
|
||||
if ((width_so_far + glyph_width + glyph_spacing / 2) > relative_x)
|
||||
return m_start + view.byte_offset_of(previous_it);
|
||||
|
@ -105,8 +105,8 @@ CSSPixelRect LineBoxFragment::selection_rect(Gfx::Font const& font) const
|
|||
|
||||
auto selection_start_in_this_fragment = max(0, range->start_offset() - m_start);
|
||||
auto selection_end_in_this_fragment = min(m_length, range->end_offset() - m_start);
|
||||
auto pixel_distance_to_first_selected_character = CSSPixels(font.width(text.substring_view(0, selection_start_in_this_fragment)));
|
||||
auto pixel_width_of_selection = CSSPixels(font.width(text.substring_view(selection_start_in_this_fragment, selection_end_in_this_fragment - selection_start_in_this_fragment))) + 1;
|
||||
auto pixel_distance_to_first_selected_character = CSSPixels::nearest_value_for(font.width(text.substring_view(0, selection_start_in_this_fragment)));
|
||||
auto pixel_width_of_selection = CSSPixels::nearest_value_for(font.width(text.substring_view(selection_start_in_this_fragment, selection_end_in_this_fragment - selection_start_in_this_fragment))) + 1;
|
||||
|
||||
auto rect = absolute_rect();
|
||||
rect.set_x(rect.x() + pixel_distance_to_first_selected_character);
|
||||
|
@ -121,8 +121,8 @@ CSSPixelRect LineBoxFragment::selection_rect(Gfx::Font const& font) const
|
|||
|
||||
auto selection_start_in_this_fragment = max(0, range->start_offset() - m_start);
|
||||
auto selection_end_in_this_fragment = m_length;
|
||||
auto pixel_distance_to_first_selected_character = CSSPixels(font.width(text.substring_view(0, selection_start_in_this_fragment)));
|
||||
auto pixel_width_of_selection = CSSPixels(font.width(text.substring_view(selection_start_in_this_fragment, selection_end_in_this_fragment - selection_start_in_this_fragment))) + 1;
|
||||
auto pixel_distance_to_first_selected_character = CSSPixels::nearest_value_for(font.width(text.substring_view(0, selection_start_in_this_fragment)));
|
||||
auto pixel_width_of_selection = CSSPixels::nearest_value_for(font.width(text.substring_view(selection_start_in_this_fragment, selection_end_in_this_fragment - selection_start_in_this_fragment))) + 1;
|
||||
|
||||
auto rect = absolute_rect();
|
||||
rect.set_x(rect.x() + pixel_distance_to_first_selected_character);
|
||||
|
@ -137,8 +137,8 @@ CSSPixelRect LineBoxFragment::selection_rect(Gfx::Font const& font) const
|
|||
|
||||
auto selection_start_in_this_fragment = 0;
|
||||
auto selection_end_in_this_fragment = min(range->end_offset() - m_start, m_length);
|
||||
auto pixel_distance_to_first_selected_character = CSSPixels(font.width(text.substring_view(0, selection_start_in_this_fragment)));
|
||||
auto pixel_width_of_selection = CSSPixels(font.width(text.substring_view(selection_start_in_this_fragment, selection_end_in_this_fragment - selection_start_in_this_fragment))) + 1;
|
||||
auto pixel_distance_to_first_selected_character = CSSPixels::nearest_value_for(font.width(text.substring_view(0, selection_start_in_this_fragment)));
|
||||
auto pixel_width_of_selection = CSSPixels::nearest_value_for(font.width(text.substring_view(selection_start_in_this_fragment, selection_end_in_this_fragment - selection_start_in_this_fragment))) + 1;
|
||||
|
||||
auto rect = absolute_rect();
|
||||
rect.set_x(rect.x() + pixel_distance_to_first_selected_character);
|
||||
|
|
|
@ -195,10 +195,10 @@ void LineBuilder::update_last_line()
|
|||
auto& font = m_context.containing_block().font();
|
||||
auto const line_height = m_context.containing_block().line_height();
|
||||
auto const font_metrics = font.pixel_metrics();
|
||||
auto const typographic_height = CSSPixels(font_metrics.ascent + font_metrics.descent);
|
||||
auto const typographic_height = CSSPixels::nearest_value_for(font_metrics.ascent + font_metrics.descent);
|
||||
auto const leading = line_height - typographic_height;
|
||||
auto const half_leading = leading / 2;
|
||||
return CSSPixels(font_metrics.ascent) + half_leading;
|
||||
return CSSPixels::nearest_value_for(font_metrics.ascent) + half_leading;
|
||||
}();
|
||||
|
||||
auto line_box_baseline = [&] {
|
||||
|
@ -207,7 +207,7 @@ void LineBuilder::update_last_line()
|
|||
auto const& font = fragment.layout_node().font();
|
||||
auto const line_height = fragment.layout_node().line_height();
|
||||
auto const font_metrics = font.pixel_metrics();
|
||||
auto const typographic_height = CSSPixels(font_metrics.ascent + font_metrics.descent);
|
||||
auto const typographic_height = CSSPixels::nearest_value_for(font_metrics.ascent + font_metrics.descent);
|
||||
auto const leading = line_height - typographic_height;
|
||||
auto const half_leading = leading / 2;
|
||||
|
||||
|
@ -215,7 +215,7 @@ void LineBuilder::update_last_line()
|
|||
|
||||
CSSPixels fragment_baseline = 0;
|
||||
if (fragment.layout_node().is_text_node()) {
|
||||
fragment_baseline = CSSPixels(font_metrics.ascent) + half_leading;
|
||||
fragment_baseline = CSSPixels::nearest_value_for(font_metrics.ascent) + half_leading;
|
||||
} else {
|
||||
auto const& box = verify_cast<Layout::Box>(fragment.layout_node());
|
||||
fragment_baseline = m_context.box_baseline(box);
|
||||
|
@ -302,11 +302,11 @@ void LineBuilder::update_last_line()
|
|||
bottom_of_inline_box = (fragment.offset().y() + fragment_box_state.content_height() + fragment_box_state.margin_box_bottom());
|
||||
} else {
|
||||
auto font_metrics = fragment.layout_node().font().pixel_metrics();
|
||||
auto typographic_height = CSSPixels(font_metrics.ascent + font_metrics.descent);
|
||||
auto typographic_height = CSSPixels::nearest_value_for(font_metrics.ascent + font_metrics.descent);
|
||||
auto leading = fragment.layout_node().line_height() - typographic_height;
|
||||
auto half_leading = leading / 2;
|
||||
top_of_inline_box = (fragment.offset().y() + fragment.baseline() - CSSPixels(font_metrics.ascent) - half_leading);
|
||||
bottom_of_inline_box = (fragment.offset().y() + fragment.baseline() + CSSPixels(font_metrics.descent) + half_leading);
|
||||
top_of_inline_box = (fragment.offset().y() + fragment.baseline() - CSSPixels::nearest_value_for(font_metrics.ascent) - half_leading);
|
||||
bottom_of_inline_box = (fragment.offset().y() + fragment.baseline() + CSSPixels::nearest_value_for(font_metrics.descent) + half_leading);
|
||||
}
|
||||
if (auto const* length_percentage = fragment.layout_node().computed_values().vertical_align().get_pointer<CSS::LengthPercentage>()) {
|
||||
if (length_percentage->is_length())
|
||||
|
|
|
@ -300,11 +300,11 @@ static CSSPixels snap_a_length_as_a_border_width(double device_pixels_per_css_pi
|
|||
|
||||
// 3. If len is greater than zero, but less than 1 device pixel, round len up to 1 device pixel.
|
||||
if (device_pixels > 0 && device_pixels < 1)
|
||||
return CSSPixels(1 / device_pixels_per_css_pixel);
|
||||
return CSSPixels::nearest_value_for(1 / device_pixels_per_css_pixel);
|
||||
|
||||
// 4. If len is greater than 1 device pixel, round it down to the nearest integer number of device pixels.
|
||||
if (device_pixels > 1)
|
||||
return CSSPixels(floor(device_pixels) / device_pixels_per_css_pixel);
|
||||
return CSSPixels::nearest_value_for(floor(device_pixels) / device_pixels_per_css_pixel);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
@ -742,7 +742,7 @@ void NodeWithStyle::apply_style(const CSS::StyleProperties& computed_style)
|
|||
// FIXME: Converting to pixels isn't really correct - values should be in "user units"
|
||||
// https://svgwg.org/svg2-draft/coords.html#TermUserUnits
|
||||
if (stroke_width->is_number())
|
||||
computed_values.set_stroke_width(CSS::Length::make_px(CSSPixels(stroke_width->as_number().number())));
|
||||
computed_values.set_stroke_width(CSS::Length::make_px(CSSPixels::nearest_value_for(stroke_width->as_number().number())));
|
||||
else if (stroke_width->is_length())
|
||||
computed_values.set_stroke_width(stroke_width->as_length().length());
|
||||
else if (stroke_width->is_percentage())
|
||||
|
|
|
@ -86,13 +86,13 @@ static ViewBoxTransform scale_and_align_viewbox_content(SVG::PreserveAspectRatio
|
|||
case SVG::PreserveAspectRatio::Align::xMidYMid:
|
||||
case SVG::PreserveAspectRatio::Align::xMidYMax:
|
||||
// Align the midpoint X value of the element's ‘viewBox’ with the midpoint X value of the SVG viewport.
|
||||
viewbox_transform.offset.translate_by((svg_box_state.content_width() - CSSPixels(view_box.width * viewbox_transform.scale_factor)) / 2, 0);
|
||||
viewbox_transform.offset.translate_by((svg_box_state.content_width() - CSSPixels::nearest_value_for(view_box.width * viewbox_transform.scale_factor)) / 2, 0);
|
||||
break;
|
||||
case SVG::PreserveAspectRatio::Align::xMaxYMin:
|
||||
case SVG::PreserveAspectRatio::Align::xMaxYMid:
|
||||
case SVG::PreserveAspectRatio::Align::xMaxYMax:
|
||||
// Align the <min-x>+<width> of the element's ‘viewBox’ with the maximum X value of the SVG viewport.
|
||||
viewbox_transform.offset.translate_by((svg_box_state.content_width() - CSSPixels(view_box.width * viewbox_transform.scale_factor)), 0);
|
||||
viewbox_transform.offset.translate_by((svg_box_state.content_width() - CSSPixels::nearest_value_for(view_box.width * viewbox_transform.scale_factor)), 0);
|
||||
break;
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
|
@ -117,13 +117,13 @@ static ViewBoxTransform scale_and_align_viewbox_content(SVG::PreserveAspectRatio
|
|||
case SVG::PreserveAspectRatio::Align::xMidYMid:
|
||||
case SVG::PreserveAspectRatio::Align::xMaxYMid:
|
||||
// Align the midpoint Y value of the element's ‘viewBox’ with the midpoint Y value of the SVG viewport.
|
||||
viewbox_transform.offset.translate_by(0, (svg_box_state.content_height() - CSSPixels(view_box.height * viewbox_transform.scale_factor)) / 2);
|
||||
viewbox_transform.offset.translate_by(0, (svg_box_state.content_height() - CSSPixels::nearest_value_for(view_box.height * viewbox_transform.scale_factor)) / 2);
|
||||
break;
|
||||
case SVG::PreserveAspectRatio::Align::xMinYMax:
|
||||
case SVG::PreserveAspectRatio::Align::xMidYMax:
|
||||
case SVG::PreserveAspectRatio::Align::xMaxYMax:
|
||||
// Align the <min-y>+<height> of the element's ‘viewBox’ with the maximum Y value of the SVG viewport.
|
||||
viewbox_transform.offset.translate_by(0, (svg_box_state.content_height() - CSSPixels(view_box.height * viewbox_transform.scale_factor)));
|
||||
viewbox_transform.offset.translate_by(0, (svg_box_state.content_height() - CSSPixels::nearest_value_for(view_box.height * viewbox_transform.scale_factor)));
|
||||
break;
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
|
@ -197,7 +197,7 @@ void SVGFormattingContext::run(Box const& box, LayoutMode layout_mode, Available
|
|||
|
||||
// Stroke increases the path's size by stroke_width/2 per side.
|
||||
auto path_bounding_box = path_transform.map(path.bounding_box()).to_type<CSSPixels>();
|
||||
CSSPixels stroke_width = CSSPixels(static_cast<double>(geometry_box.dom_node().visible_stroke_width()) * viewbox_scale);
|
||||
CSSPixels stroke_width = CSSPixels::nearest_value_for(static_cast<double>(geometry_box.dom_node().visible_stroke_width()) * viewbox_scale);
|
||||
path_bounding_box.inflate(stroke_width, stroke_width);
|
||||
geometry_box_state.set_content_offset(path_bounding_box.top_left());
|
||||
geometry_box_state.set_content_width(path_bounding_box.width());
|
||||
|
|
|
@ -265,11 +265,11 @@ void TableFormattingContext::compute_intrinsic_percentage(size_t max_cell_span)
|
|||
auto cell_start_rc_index = cell_index<RowOrColumn>(cell);
|
||||
auto cell_end_rc_index = cell_start_rc_index + cell_span_value;
|
||||
// 1. Start with the percentage contribution of the cell.
|
||||
CSSPixels cell_contribution = CSSPixels(cell_percentage_contribution<RowOrColumn>(cell));
|
||||
CSSPixels cell_contribution = CSSPixels::nearest_value_for(cell_percentage_contribution<RowOrColumn>(cell));
|
||||
// 2. Subtract the intrinsic percentage width of the column based on cells of span up to N-1 of all columns
|
||||
// that the cell spans. If this gives a negative result, change it to 0%.
|
||||
for (auto rc_index = cell_start_rc_index; rc_index < cell_end_rc_index; rc_index++) {
|
||||
cell_contribution -= CSSPixels(rows_or_columns[rc_index].intrinsic_percentage);
|
||||
cell_contribution -= CSSPixels::nearest_value_for(rows_or_columns[rc_index].intrinsic_percentage);
|
||||
cell_contribution = max(cell_contribution, 0);
|
||||
}
|
||||
// Compute the sum of the non-spanning max-content sizes of all rows / columns spanned by the cell that have an intrinsic percentage
|
||||
|
@ -380,12 +380,12 @@ void TableFormattingContext::compute_table_measures()
|
|||
auto clamped_diff_to_baseline_min = min(
|
||||
max(cell_min_size<RowOrColumn>(cell) - baseline_min_content_size - baseline_border_spacing, 0),
|
||||
baseline_max_content_size - baseline_min_content_size);
|
||||
cell_min_contribution += CSSPixels(normalized_max_min_diff * clamped_diff_to_baseline_min);
|
||||
cell_min_contribution += CSSPixels::nearest_value_for(normalized_max_min_diff * clamped_diff_to_baseline_min);
|
||||
// the product of:
|
||||
// - the ratio of the max-content size based on cells of span up to N-1 of the column to the baseline max-content size
|
||||
// - the outer min-content size of the cell minus the baseline max-content size and baseline border spacing, or 0 if this is negative
|
||||
if (baseline_max_content_size != 0) {
|
||||
cell_min_contribution += CSSPixels(rows_or_columns[rc_index].max_size / static_cast<double>(baseline_max_content_size))
|
||||
cell_min_contribution += CSSPixels::nearest_value_for(rows_or_columns[rc_index].max_size / static_cast<double>(baseline_max_content_size))
|
||||
* max(CSSPixels(0), cell_min_size<RowOrColumn>(cell) - baseline_max_content_size - baseline_border_spacing);
|
||||
}
|
||||
|
||||
|
@ -396,7 +396,7 @@ void TableFormattingContext::compute_table_measures()
|
|||
// - the ratio of the max-content size based on cells of span up to N-1 of the column to the baseline max-content size
|
||||
// - the outer max-content size of the cell minus the baseline max-content size and the baseline border spacing, or 0 if this is negative
|
||||
if (baseline_max_content_size != 0) {
|
||||
cell_max_contribution += CSSPixels(rows_or_columns[rc_index].max_size / static_cast<double>(baseline_max_content_size))
|
||||
cell_max_contribution += CSSPixels::nearest_value_for(rows_or_columns[rc_index].max_size / static_cast<double>(baseline_max_content_size))
|
||||
* max(CSSPixels(0), cell_max_size<RowOrColumn>(cell) - baseline_max_content_size - baseline_border_spacing);
|
||||
}
|
||||
cell_min_contributions_by_rc_index[rc_index].append(cell_min_contribution);
|
||||
|
@ -496,7 +496,7 @@ void TableFormattingContext::compute_table_width()
|
|||
for (auto& cell : m_cells) {
|
||||
auto const& cell_width = cell.box->computed_values().width();
|
||||
if (cell_width.is_percentage()) {
|
||||
adjusted_used_width = CSSPixels(ceil(100 / cell_width.percentage().value() * cell.outer_max_width.to_double()));
|
||||
adjusted_used_width = CSSPixels::nearest_value_for(ceil(100 / cell_width.percentage().value() * cell.outer_max_width.to_double()));
|
||||
if (width_of_table_containing_block.is_definite())
|
||||
used_width = min(max(used_width, adjusted_used_width), width_of_table_containing_block.to_px_or_zero());
|
||||
else
|
||||
|
@ -555,7 +555,7 @@ void TableFormattingContext::assign_columns_width_linear_combination(Vector<CSSP
|
|||
auto candidate_weight = (available_width - columns_total_used_width) / static_cast<double>(columns_total_candidate_width - columns_total_used_width);
|
||||
for (size_t i = 0; i < m_columns.size(); ++i) {
|
||||
auto& column = m_columns[i];
|
||||
column.used_width = CSSPixels(candidate_weight * candidate_widths[i] + (1 - candidate_weight) * column.used_width);
|
||||
column.used_width = CSSPixels::nearest_value_for(candidate_weight * candidate_widths[i] + (1 - candidate_weight) * column.used_width);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -576,7 +576,7 @@ bool TableFormattingContext::distribute_excess_width_proportionally_to_base_widt
|
|||
VERIFY(total_base_width > 0);
|
||||
for (auto& column : m_columns) {
|
||||
if (column_filter(column)) {
|
||||
column.used_width += CSSPixels(excess_width * base_width_getter(column) / static_cast<double>(total_base_width));
|
||||
column.used_width += CSSPixels::nearest_value_for(excess_width * base_width_getter(column) / static_cast<double>(total_base_width));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -618,7 +618,7 @@ bool TableFormattingContext::distribute_excess_width_by_intrinsic_percentage(CSS
|
|||
}
|
||||
for (auto& column : m_columns) {
|
||||
if (column_filter(column)) {
|
||||
column.used_width += CSSPixels(excess_width * column.intrinsic_percentage / total_percentage_width);
|
||||
column.used_width += CSSPixels::nearest_value_for(excess_width * column.intrinsic_percentage / total_percentage_width);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -660,7 +660,7 @@ void TableFormattingContext::distribute_width_to_columns()
|
|||
for (size_t i = 0; i < m_columns.size(); ++i) {
|
||||
auto& column = m_columns[i];
|
||||
if (column.has_intrinsic_percentage) {
|
||||
candidate_widths[i] = max(column.min_size, CSSPixels(column.intrinsic_percentage / 100 * available_width));
|
||||
candidate_widths[i] = max(column.min_size, CSSPixels::nearest_value_for(column.intrinsic_percentage / 100 * available_width));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -990,7 +990,7 @@ void TableFormattingContext::distribute_height_to_rows()
|
|||
for (auto& row : m_rows) {
|
||||
auto weight = row.reference_height / static_cast<double>(sum_reference_height);
|
||||
auto final_height = m_table_height * weight;
|
||||
row.final_height = CSSPixels(final_height);
|
||||
row.final_height = CSSPixels::nearest_value_for(final_height);
|
||||
}
|
||||
} else if (rows_with_auto_height.size() > 0) {
|
||||
// Else, if the table owns any “auto-height” row (a row whose size is only determined by its content size and
|
||||
|
|
|
@ -263,7 +263,7 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet
|
|||
repeat_x = false;
|
||||
} else {
|
||||
auto space = fmod(background_positioning_area.width().to_double(), image_rect.width().to_double());
|
||||
x_step = image_rect.width() + CSSPixels(space / static_cast<double>(whole_images - 1));
|
||||
x_step = image_rect.width() + CSSPixels::nearest_value_for(space / static_cast<double>(whole_images - 1));
|
||||
repeat_x = true;
|
||||
}
|
||||
break;
|
||||
|
@ -294,7 +294,7 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet
|
|||
repeat_y = false;
|
||||
} else {
|
||||
auto space = fmod(background_positioning_area.height().to_float(), image_rect.height().to_float());
|
||||
y_step = image_rect.height() + CSSPixels(static_cast<double>(space) / static_cast<double>(whole_images - 1));
|
||||
y_step = image_rect.height() + CSSPixels::nearest_value_for(static_cast<double>(space) / static_cast<double>(whole_images - 1));
|
||||
repeat_y = true;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -117,7 +117,7 @@ LinearGradientData resolve_linear_gradient_data(Layout::NodeWithStyleAndBoxModel
|
|||
|
||||
auto resolved_color_stops = resolve_color_stop_positions(
|
||||
node, linear_gradient.color_stop_list(), [&](auto const& length_percentage) {
|
||||
return length_percentage.to_px(node, CSSPixels(gradient_length_px)).to_float() / static_cast<float>(gradient_length_px);
|
||||
return length_percentage.to_px(node, CSSPixels::nearest_value_for(gradient_length_px)).to_float() / static_cast<float>(gradient_length_px);
|
||||
},
|
||||
linear_gradient.is_repeating());
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ DevicePixelSize PaintContext::rounded_device_size(CSSPixelSize size) const
|
|||
|
||||
CSSPixels PaintContext::scale_to_css_pixels(DevicePixels device_pixels) const
|
||||
{
|
||||
return CSSPixels(device_pixels.value() / m_device_pixels_per_css_pixel);
|
||||
return CSSPixels::nearest_value_for(device_pixels.value() / m_device_pixels_per_css_pixel);
|
||||
}
|
||||
|
||||
CSSPixelPoint PaintContext::scale_to_css_point(DevicePixelPoint point) const
|
||||
|
|
|
@ -258,8 +258,8 @@ void PaintableBox::paint(PaintContext& context, PaintPhase phase) const
|
|||
auto size_text_rect = border_rect;
|
||||
size_text_rect.set_y(border_rect.y() + border_rect.height());
|
||||
size_text_rect.set_top(size_text_rect.top());
|
||||
size_text_rect.set_width(CSSPixels(font.width(size_text)) + 4);
|
||||
size_text_rect.set_height(CSSPixels(font.pixel_size()) + 4);
|
||||
size_text_rect.set_width(CSSPixels::nearest_value_for(font.width(size_text)) + 4);
|
||||
size_text_rect.set_height(CSSPixels::nearest_value_for(font.pixel_size()) + 4);
|
||||
auto size_text_device_rect = context.enclosing_device_rect(size_text_rect).to_type<int>();
|
||||
context.painter().fill_rect(size_text_device_rect, context.palette().color(Gfx::ColorRole::Tooltip));
|
||||
context.painter().draw_rect(size_text_device_rect, context.palette().threed_shadow1());
|
||||
|
@ -503,7 +503,7 @@ static void paint_cursor_if_needed(PaintContext& context, Layout::TextNode const
|
|||
auto fragment_rect = fragment.absolute_rect();
|
||||
|
||||
CSSPixelRect cursor_rect {
|
||||
fragment_rect.x() + CSSPixels(text_node.font().width(fragment.text().substring_view(0, text_node.browsing_context().cursor_position().offset() - fragment.start()))),
|
||||
fragment_rect.x() + CSSPixels::nearest_value_for(text_node.font().width(fragment.text().substring_view(0, text_node.browsing_context().cursor_position().offset() - fragment.start()))),
|
||||
fragment_rect.top(),
|
||||
1,
|
||||
fragment_rect.height()
|
||||
|
@ -518,7 +518,7 @@ static void paint_text_decoration(PaintContext& context, Gfx::Painter& painter,
|
|||
{
|
||||
auto& font = fragment.layout_node().font();
|
||||
auto fragment_box = fragment.absolute_rect();
|
||||
CSSPixels glyph_height = CSSPixels(font.pixel_size());
|
||||
CSSPixels glyph_height = CSSPixels::nearest_value_for(font.pixel_size());
|
||||
auto baseline = fragment_box.height() / 2 - (glyph_height + 4) / 2 + glyph_height;
|
||||
|
||||
auto line_color = text_node.computed_values().text_decoration_color();
|
||||
|
|
|
@ -78,13 +78,21 @@ public:
|
|||
template<FloatingPoint F>
|
||||
explicit CSSPixels(F value)
|
||||
{
|
||||
*this = nearest_value_for(value);
|
||||
}
|
||||
|
||||
template<FloatingPoint F>
|
||||
static CSSPixels nearest_value_for(F value)
|
||||
{
|
||||
i32 raw_value = 0;
|
||||
if (!isnan(value))
|
||||
m_value = AK::clamp_to_int(value * fixed_point_denominator);
|
||||
raw_value = AK::clamp_to_int(value * fixed_point_denominator);
|
||||
// Note: The resolution of CSSPixels is 0.015625, so care must be taken when converting
|
||||
// floats/doubles to CSSPixels as small values (such as scale factors) can underflow to zero,
|
||||
// or otherwise produce inaccurate results (when scaled back up).
|
||||
if (m_value == 0 && value != 0)
|
||||
if (raw_value == 0 && value != 0)
|
||||
dbgln_if(LIBWEB_CSS_DEBUG, "CSSPixels: Conversion from float or double underflowed to zero");
|
||||
return from_raw(raw_value);
|
||||
}
|
||||
|
||||
template<Unsigned U>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue