From 655d9d14628d73113d0e1a891fe79c3b3052caf3 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 24 May 2023 10:50:57 +0200 Subject: LibWeb: Make CSSPixels and Length use 64-bit (double) floating point This fixes a plethora of rounding problems on many websites. In the future, we may want to replace this with fixed-point arithmetic (bug #18566) for performance (and consistency with other engines), but in the meantime this makes the web look a bit better. :^) There's a lot more things that could be converted to doubles, which would reduce the amount of casting necessary in this patch. We can do that incrementally, however. --- .../Libraries/LibWeb/Painting/BackgroundPainting.cpp | 16 ++++++++-------- Userland/Libraries/LibWeb/Painting/BorderPainting.cpp | 10 +++++----- Userland/Libraries/LibWeb/Painting/GradientPainting.cpp | 4 ++-- Userland/Libraries/LibWeb/Painting/MarkerPaintable.cpp | 4 ++-- Userland/Libraries/LibWeb/Painting/PaintContext.cpp | 2 +- Userland/Libraries/LibWeb/Painting/PaintContext.h | 6 +++--- Userland/Libraries/LibWeb/Painting/PaintableBox.cpp | 4 ++-- .../Libraries/LibWeb/Painting/SVGGeometryPaintable.cpp | 4 ++-- Userland/Libraries/LibWeb/Painting/StackingContext.cpp | 4 ++-- Userland/Libraries/LibWeb/Painting/VideoPaintable.cpp | 2 +- 10 files changed, 28 insertions(+), 28 deletions(-) (limited to 'Userland/Libraries/LibWeb/Painting') diff --git a/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp b/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp index 0661debd4b..a78e4b76a4 100644 --- a/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp +++ b/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp @@ -148,16 +148,16 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet CSSPixelRect image_rect; switch (layer.size_type) { case CSS::BackgroundSize::Contain: { - float max_width_ratio = (background_positioning_area.width() / natural_image_width).value(); - float max_height_ratio = (background_positioning_area.height() / natural_image_height).value(); - float ratio = min(max_width_ratio, max_height_ratio); + double max_width_ratio = (background_positioning_area.width() / natural_image_width).value(); + double max_height_ratio = (background_positioning_area.height() / natural_image_height).value(); + double ratio = min(max_width_ratio, max_height_ratio); image_rect.set_size(natural_image_width * ratio, natural_image_height * ratio); break; } case CSS::BackgroundSize::Cover: { - float max_width_ratio = (background_positioning_area.width() / natural_image_width).value(); - float max_height_ratio = (background_positioning_area.height() / natural_image_height).value(); - float ratio = max(max_width_ratio, max_height_ratio); + double max_width_ratio = (background_positioning_area.width() / natural_image_width).value(); + double max_height_ratio = (background_positioning_area.height() / natural_image_height).value(); + double ratio = max(max_width_ratio, max_height_ratio); image_rect.set_size(natural_image_width * ratio, natural_image_height * ratio); break; } @@ -253,7 +253,7 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet repeat_x = false; } else { auto space = fmod(background_positioning_area.width(), image_rect.width()); - x_step = image_rect.width() + (space / (float)(whole_images - 1)); + x_step = image_rect.width() + (space / static_cast(whole_images - 1)); repeat_x = true; } break; @@ -284,7 +284,7 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet repeat_y = false; } else { auto space = fmod(background_positioning_area.height(), image_rect.height()); - y_step = image_rect.height() + ((float)space / (float)(whole_images - 1)); + y_step = image_rect.height() + (static_cast(space) / static_cast(whole_images - 1)); repeat_y = true; } break; diff --git a/Userland/Libraries/LibWeb/Painting/BorderPainting.cpp b/Userland/Libraries/LibWeb/Painting/BorderPainting.cpp index 80f6bda200..9f92331a0f 100644 --- a/Userland/Libraries/LibWeb/Painting/BorderPainting.cpp +++ b/Userland/Libraries/LibWeb/Painting/BorderPainting.cpp @@ -33,14 +33,14 @@ BorderRadiiData normalized_border_radii_data(Layout::Node const& node, CSSPixelR // Scale overlapping curves according to https://www.w3.org/TR/css-backgrounds-3/#corner-overlap CSSPixels f = 1.0f; - auto width_reciprocal = 1.0f / rect.width().value(); - auto height_reciprocal = 1.0f / rect.height().value(); + auto width_reciprocal = 1.0 / rect.width().value(); + auto height_reciprocal = 1.0 / rect.height().value(); f = max(f, width_reciprocal * (top_left_radius_px.horizontal_radius + top_right_radius_px.horizontal_radius)); f = max(f, height_reciprocal * (top_right_radius_px.vertical_radius + bottom_right_radius_px.vertical_radius)); f = max(f, width_reciprocal * (bottom_left_radius_px.horizontal_radius + bottom_right_radius_px.horizontal_radius)); f = max(f, height_reciprocal * (top_left_radius_px.vertical_radius + bottom_left_radius_px.vertical_radius)); - f = 1.0f / f.value(); + f = 1.0 / f.value(); top_left_radius_px.horizontal_radius *= f; top_left_radius_px.vertical_radius *= f; @@ -149,8 +149,8 @@ void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const& auto draw_border = [&](auto const& border, auto const& radius, auto const& opposite_border, auto const& opposite_radius, auto p1_step_translate, auto p2_step_translate) { auto [p1, p2] = points_for_edge(edge, rect); - auto p1_step = radius ? 0 : border.width / static_cast(device_pixel_width.value()); - auto p2_step = opposite_radius ? 0 : opposite_border.width / static_cast(device_pixel_width.value()); + auto p1_step = radius ? 0 : border.width / device_pixel_width.value(); + auto p2_step = opposite_radius ? 0 : opposite_border.width / device_pixel_width.value(); for (DevicePixels i = 0; i < device_pixel_width; ++i) { draw_horizontal_or_vertical_line(p1, p2); p1_step_translate(p1, p1_step); diff --git a/Userland/Libraries/LibWeb/Painting/GradientPainting.cpp b/Userland/Libraries/LibWeb/Painting/GradientPainting.cpp index 3d0543478d..78cb3db804 100644 --- a/Userland/Libraries/LibWeb/Painting/GradientPainting.cpp +++ b/Userland/Libraries/LibWeb/Painting/GradientPainting.cpp @@ -111,11 +111,11 @@ static ColorStopData resolve_color_stop_positions(auto const& color_stop_list, a LinearGradientData resolve_linear_gradient_data(Layout::Node const& node, CSSPixelSize gradient_size, CSS::LinearGradientStyleValue const& linear_gradient) { auto gradient_angle = linear_gradient.angle_degrees(gradient_size); - auto gradient_length_px = Gfx::calculate_gradient_length(gradient_size, gradient_angle); + auto gradient_length_px = Gfx::calculate_gradient_length(gradient_size.to_type().to_type(), gradient_angle); auto resolved_color_stops = resolve_color_stop_positions( linear_gradient.color_stop_list(), [&](auto const& length_percentage) { - return length_percentage.to_px(node, gradient_length_px).value() / gradient_length_px; + return length_percentage.to_px(node, gradient_length_px).value() / static_cast(gradient_length_px); }, linear_gradient.is_repeating()); diff --git a/Userland/Libraries/LibWeb/Painting/MarkerPaintable.cpp b/Userland/Libraries/LibWeb/Painting/MarkerPaintable.cpp index 5e347f3454..4263a3b44e 100644 --- a/Userland/Libraries/LibWeb/Painting/MarkerPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/MarkerPaintable.cpp @@ -32,10 +32,10 @@ void MarkerPaintable::paint(PaintContext& context, PaintPhase phase) const return; // FIXME: All this does is round to the nearest whole CSS pixel, but it's goofy. - CSSPixelRect enclosing = absolute_rect().to_type().to_rounded().to_type(); + CSSPixelRect enclosing = absolute_rect().to_type().to_type().to_rounded().to_type(); auto device_enclosing = context.enclosing_device_rect(enclosing); - CSSPixels marker_width = enclosing.height() / 2.0f; + CSSPixels marker_width = enclosing.height() / 2.0; if (auto const* list_style_image = layout_box().list_style_image()) { CSSPixelRect image_rect { diff --git a/Userland/Libraries/LibWeb/Painting/PaintContext.cpp b/Userland/Libraries/LibWeb/Painting/PaintContext.cpp index 86c40fe89a..f767a2e03f 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintContext.cpp +++ b/Userland/Libraries/LibWeb/Painting/PaintContext.cpp @@ -10,7 +10,7 @@ namespace Web { -PaintContext::PaintContext(Gfx::Painter& painter, Palette const& palette, float device_pixels_per_css_pixel) +PaintContext::PaintContext(Gfx::Painter& painter, Palette const& palette, double device_pixels_per_css_pixel) : m_painter(painter) , m_palette(palette) , m_device_pixels_per_css_pixel(device_pixels_per_css_pixel) diff --git a/Userland/Libraries/LibWeb/Painting/PaintContext.h b/Userland/Libraries/LibWeb/Painting/PaintContext.h index d8fd425147..0f590eefa6 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintContext.h +++ b/Userland/Libraries/LibWeb/Painting/PaintContext.h @@ -18,7 +18,7 @@ namespace Web { class PaintContext { public: - PaintContext(Gfx::Painter& painter, Palette const& palette, float device_pixels_per_css_pixel); + PaintContext(Gfx::Painter& painter, Palette const& palette, double device_pixels_per_css_pixel); Gfx::Painter& painter() const { return m_painter; } Palette const& palette() const { return m_palette; } @@ -64,13 +64,13 @@ public: return clone; } - float device_pixels_per_css_pixel() const { return m_device_pixels_per_css_pixel; } + double device_pixels_per_css_pixel() const { return m_device_pixels_per_css_pixel; } private: Gfx::Painter& m_painter; Palette m_palette; Optional m_svg_context; - float m_device_pixels_per_css_pixel; + double m_device_pixels_per_css_pixel { 0 }; DevicePixelRect m_device_viewport_rect; bool m_should_show_line_box_borders { false }; bool m_focus { false }; diff --git a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp index e243c8475f..e358622e3a 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp +++ b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp @@ -155,7 +155,7 @@ void PaintableBox::paint(PaintContext& context, PaintPhase phase) const if (should_clip_rect) { context.painter().save(); auto border_box = absolute_border_box_rect(); - context.painter().add_clip_rect(context.rounded_device_rect(clip_rect.to_rect().resolved(Paintable::layout_node(), border_box.to_type()).to_type()).to_type()); + context.painter().add_clip_rect(context.rounded_device_rect(clip_rect.to_rect().resolved(Paintable::layout_node(), border_box.to_type()).to_type()).to_type()); } paint_backdrop_filter(context); paint_background(context); @@ -434,7 +434,7 @@ static void paint_text_decoration(PaintContext& context, Gfx::Painter& painter, CSSPixels css_line_thickness = [&] { CSS::Length computed_thickness = text_node.computed_values().text_decoration_thickness().resolved(text_node, CSS::Length(1, CSS::Length::Type::Em)); if (computed_thickness.is_auto()) - return max(glyph_height * 0.1f, 1.f); + return max(glyph_height * 0.1, 1.); return computed_thickness.to_px(text_node); }(); diff --git a/Userland/Libraries/LibWeb/Painting/SVGGeometryPaintable.cpp b/Userland/Libraries/LibWeb/Painting/SVGGeometryPaintable.cpp index 09ac1270a5..7fc3076b39 100644 --- a/Userland/Libraries/LibWeb/Painting/SVGGeometryPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/SVGGeometryPaintable.cpp @@ -36,7 +36,7 @@ Optional SVGGeometryPaintable::hit_test(CSSPixelPoint position, H if (auto transform = layout_box().layout_transform(); transform.has_value()) { auto transformed_bounding_box = transform->map_to_quad( const_cast(geometry_element).get_path().bounding_box()); - if (!transformed_bounding_box.contains(position.to_type())) + if (!transformed_bounding_box.contains(position.to_type().to_type())) return {}; } return result; @@ -92,7 +92,7 @@ void SVGGeometryPaintable::paint(PaintContext& context, PaintPhase phase) const auto svg_viewport = [&] { if (maybe_view_box.has_value()) return Gfx::FloatRect { maybe_view_box->min_x, maybe_view_box->min_y, maybe_view_box->width, maybe_view_box->height }; - return Gfx::FloatRect { { 0, 0 }, svg_context.svg_element_size().to_type() }; + return Gfx::FloatRect { { 0, 0 }, svg_context.svg_element_size().to_type().to_type() }; }(); SVG::SVGPaintContext paint_context { diff --git a/Userland/Libraries/LibWeb/Painting/StackingContext.cpp b/Userland/Libraries/LibWeb/Painting/StackingContext.cpp index 8a98a76afa..4c83296c34 100644 --- a/Userland/Libraries/LibWeb/Painting/StackingContext.cpp +++ b/Userland/Libraries/LibWeb/Painting/StackingContext.cpp @@ -232,7 +232,7 @@ Gfx::FloatMatrix4x4 StackingContext::get_transformation_matrix(CSS::Transformati auto count = transformation.values.size(); auto value = [this, transformation](size_t index, Optional reference_length = {}) -> float { return transformation.values[index].visit( - [this, reference_length](CSS::LengthPercentage const& value) { + [this, reference_length](CSS::LengthPercentage const& value) -> float { if (reference_length.has_value()) { return value.resolved(m_box, reference_length.value()).to_px(m_box).value(); } @@ -430,7 +430,7 @@ Gfx::FloatPoint StackingContext::compute_transform_origin() const auto reference_box = paintable_box().absolute_border_box_rect(); auto x = reference_box.left() + style_value.x.to_px(m_box, reference_box.width()); auto y = reference_box.top() + style_value.y.to_px(m_box, reference_box.height()); - return { x, y }; + return { static_cast(x.value()), static_cast(y.value()) }; } template diff --git a/Userland/Libraries/LibWeb/Painting/VideoPaintable.cpp b/Userland/Libraries/LibWeb/Painting/VideoPaintable.cpp index 96a5d36232..078db4eaca 100644 --- a/Userland/Libraries/LibWeb/Painting/VideoPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/VideoPaintable.cpp @@ -378,7 +378,7 @@ VideoPaintable::DispatchEventOfSameName VideoPaintable::handle_mouseup(Badgecontains(position)) { auto x_offset = position.x() - cached_layout_boxes.timeline_rect->x(); - auto x_percentage = static_cast(x_offset) / static_cast(cached_layout_boxes.timeline_rect->width()); + auto x_percentage = static_cast(x_offset) / static_cast(cached_layout_boxes.timeline_rect->width()); auto position = static_cast(x_percentage) * video_element.duration(); video_element.set_current_time(position); -- cgit v1.2.3