Procházet zdrojové kódy

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.
Jelle Raaijmakers před 2 roky
rodič
revize
b79fd3d1a9

+ 3 - 1
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;

+ 4 - 2
Userland/Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.cpp

@@ -102,8 +102,10 @@ Optional<CSSPixels> 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<int>(), *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<int>());
+        context.painter().draw_scaled_bitmap(dest_rect.to_type<int>(), *b, bitmap(0)->rect(), 1.f, scaling_mode);
+    }
 }
 
 }

+ 2 - 1
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<HTML::HTMLCanvasElement&>(layout_box().dom_node()).present();
-            context.painter().draw_scaled_bitmap(canvas_rect.to_type<int>(), *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<int>());
+            context.painter().draw_scaled_bitmap(canvas_rect.to_type<int>(), *layout_box().dom_node().bitmap(), layout_box().dom_node().bitmap()->rect(), 1.0f, scaling_mode);
         }
     }
 }

+ 2 - 1
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<int>(), *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<int>());
+            context.painter().draw_scaled_bitmap(image_rect.to_type<int>(), *bitmap, bitmap->rect(), 1.f, scaling_mode);
         }
     }
 }

+ 2 - 1
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<int>(), *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<int>());
+        context.painter().draw_scaled_bitmap(video_rect.to_type<int>(), *frame, frame->rect(), 1.f, scaling_mode);
     };
 
     auto paint_transparent_black = [&]() {