From 7652dbd9833f1b85e95b3d10c80079d645d96c66 Mon Sep 17 00:00:00 2001 From: Jelle Raaijmakers Date: Fri, 19 May 2023 00:41:12 +0200 Subject: [PATCH] LibWeb: Use box sampling instead of bilinear scaling when downscaling As a heuristic, either the width or height of the scaled image should decrease for box sampling to be used. Otherwise, we use bilinear scaling. --- Userland/Libraries/LibWeb/CSS/ComputedValues.h | 4 +++- .../Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.cpp | 6 ++++-- Userland/Libraries/LibWeb/Painting/CanvasPaintable.cpp | 3 ++- Userland/Libraries/LibWeb/Painting/ImagePaintable.cpp | 3 ++- Userland/Libraries/LibWeb/Painting/VideoPaintable.cpp | 3 ++- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/Userland/Libraries/LibWeb/CSS/ComputedValues.h b/Userland/Libraries/LibWeb/CSS/ComputedValues.h index 9b126ce330f..5296c06ee6f 100644 --- a/Userland/Libraries/LibWeb/CSS/ComputedValues.h +++ b/Userland/Libraries/LibWeb/CSS/ComputedValues.h @@ -185,12 +185,14 @@ struct BorderRadiusData { }; // FIXME: Find a better place for this helper. -inline Gfx::Painter::ScalingMode to_gfx_scaling_mode(CSS::ImageRendering css_value) +inline Gfx::Painter::ScalingMode to_gfx_scaling_mode(CSS::ImageRendering css_value, Gfx::IntRect source, Gfx::IntRect target) { switch (css_value) { case CSS::ImageRendering::Auto: case CSS::ImageRendering::HighQuality: case CSS::ImageRendering::Smooth: + if (target.width() < source.width() || target.height() < source.height()) + return Gfx::Painter::ScalingMode::BoxSampling; return Gfx::Painter::ScalingMode::BilinearBlend; case CSS::ImageRendering::CrispEdges: return Gfx::Painter::ScalingMode::NearestNeighbor; diff --git a/Userland/Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.cpp b/Userland/Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.cpp index 77f20c19c30..872f09c31c7 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.cpp @@ -102,8 +102,10 @@ Optional ImageStyleValue::natural_height() const void ImageStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering image_rendering) const { - if (auto* b = bitmap(m_current_frame_index); b != nullptr) - context.painter().draw_scaled_bitmap(dest_rect.to_type(), *b, bitmap(0)->rect(), 1.0f, to_gfx_scaling_mode(image_rendering)); + if (auto* b = bitmap(m_current_frame_index); b != nullptr) { + auto scaling_mode = to_gfx_scaling_mode(image_rendering, bitmap(0)->rect(), dest_rect.to_type()); + context.painter().draw_scaled_bitmap(dest_rect.to_type(), *b, bitmap(0)->rect(), 1.f, scaling_mode); + } } } diff --git a/Userland/Libraries/LibWeb/Painting/CanvasPaintable.cpp b/Userland/Libraries/LibWeb/Painting/CanvasPaintable.cpp index 034c4749032..83e2735610d 100644 --- a/Userland/Libraries/LibWeb/Painting/CanvasPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/CanvasPaintable.cpp @@ -41,7 +41,8 @@ void CanvasPaintable::paint(PaintContext& context, PaintPhase phase) const if (layout_box().dom_node().bitmap()) { // FIXME: Remove this const_cast. const_cast(layout_box().dom_node()).present(); - context.painter().draw_scaled_bitmap(canvas_rect.to_type(), *layout_box().dom_node().bitmap(), layout_box().dom_node().bitmap()->rect(), 1.0f, to_gfx_scaling_mode(computed_values().image_rendering())); + auto scaling_mode = to_gfx_scaling_mode(computed_values().image_rendering(), layout_box().dom_node().bitmap()->rect(), canvas_rect.to_type()); + context.painter().draw_scaled_bitmap(canvas_rect.to_type(), *layout_box().dom_node().bitmap(), layout_box().dom_node().bitmap()->rect(), 1.0f, scaling_mode); } } } diff --git a/Userland/Libraries/LibWeb/Painting/ImagePaintable.cpp b/Userland/Libraries/LibWeb/Painting/ImagePaintable.cpp index 6b0190b25c7..4c8ca279d0d 100644 --- a/Userland/Libraries/LibWeb/Painting/ImagePaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/ImagePaintable.cpp @@ -64,7 +64,8 @@ void ImagePaintable::paint(PaintContext& context, PaintPhase phase) const } else if (auto bitmap = layout_box().image_provider().current_image_bitmap()) { auto image_rect = context.rounded_device_rect(absolute_rect()); ScopedCornerRadiusClip corner_clip { context, context.painter(), image_rect, normalized_border_radii_data(ShrinkRadiiForBorders::Yes) }; - context.painter().draw_scaled_bitmap(image_rect.to_type(), *bitmap, bitmap->rect(), 1.0f, to_gfx_scaling_mode(computed_values().image_rendering())); + auto scaling_mode = to_gfx_scaling_mode(computed_values().image_rendering(), bitmap->rect(), image_rect.to_type()); + context.painter().draw_scaled_bitmap(image_rect.to_type(), *bitmap, bitmap->rect(), 1.f, scaling_mode); } } } diff --git a/Userland/Libraries/LibWeb/Painting/VideoPaintable.cpp b/Userland/Libraries/LibWeb/Painting/VideoPaintable.cpp index ccc697aaa6c..96a5d36232b 100644 --- a/Userland/Libraries/LibWeb/Painting/VideoPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/VideoPaintable.cpp @@ -135,7 +135,8 @@ void VideoPaintable::paint(PaintContext& context, PaintPhase phase) const } auto paint_frame = [&](auto const& frame) { - context.painter().draw_scaled_bitmap(video_rect.to_type(), *frame, frame->rect(), 1.0f, to_gfx_scaling_mode(computed_values().image_rendering())); + auto scaling_mode = to_gfx_scaling_mode(computed_values().image_rendering(), frame->rect(), video_rect.to_type()); + context.painter().draw_scaled_bitmap(video_rect.to_type(), *frame, frame->rect(), 1.f, scaling_mode); }; auto paint_transparent_black = [&]() {