diff options
author | Andreas Kling <kling@serenityos.org> | 2023-05-24 10:50:57 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2023-05-24 14:40:35 +0200 |
commit | 655d9d14628d73113d0e1a891fe79c3b3052caf3 (patch) | |
tree | 7f04312628c7ebda45b174043bc02adab8385480 /Userland/Libraries/LibWeb/Painting | |
parent | 30262d702356cdef330a7a3e57da3183b643ba86 (diff) | |
download | serenity-655d9d14628d73113d0e1a891fe79c3b3052caf3.zip |
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.
Diffstat (limited to 'Userland/Libraries/LibWeb/Painting')
10 files changed, 28 insertions, 28 deletions
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<double>(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<double>(space) / static_cast<double>(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<float>(device_pixel_width.value()); - auto p2_step = opposite_radius ? 0 : opposite_border.width / static_cast<float>(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<double>().to_type<float>(), 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<double>(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<float>().to_rounded<float>().to_type<CSSPixels>(); + CSSPixelRect enclosing = absolute_rect().to_type<double>().to_type<float>().to_rounded<float>().to_type<CSSPixels>(); 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<SVGContext> 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<float>()).to_type<CSSPixels>()).to_type<int>()); + context.painter().add_clip_rect(context.rounded_device_rect(clip_rect.to_rect().resolved(Paintable::layout_node(), border_box.to_type<double>()).to_type<CSSPixels>()).to_type<int>()); } 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<HitTestResult> 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<SVG::SVGGeometryElement&>(geometry_element).get_path().bounding_box()); - if (!transformed_bounding_box.contains(position.to_type<float>())) + if (!transformed_bounding_box.contains(position.to_type<double>().to_type<float>())) 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<float>() }; + return Gfx::FloatRect { { 0, 0 }, svg_context.svg_element_size().to_type<double>().to_type<float>() }; }(); 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<CSS::Length const&> 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<float>(x.value()), static_cast<float>(y.value()) }; } template<typename U, typename Callback> 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(Badge<Eve if (cached_layout_boxes.timeline_rect.has_value() && cached_layout_boxes.timeline_rect->contains(position)) { auto x_offset = position.x() - cached_layout_boxes.timeline_rect->x(); - auto x_percentage = static_cast<float>(x_offset) / static_cast<float>(cached_layout_boxes.timeline_rect->width()); + auto x_percentage = static_cast<double>(x_offset) / static_cast<double>(cached_layout_boxes.timeline_rect->width()); auto position = static_cast<double>(x_percentage) * video_element.duration(); video_element.set_current_time(position); |