From d5c913082b5efd7f8985ba9b76979edb28bc507a Mon Sep 17 00:00:00 2001 From: Tim Ledbetter Date: Fri, 10 Mar 2023 17:29:00 +0000 Subject: [PATCH] Tests: Add tests to verify alpha values are premultiplied when scaling --- Tests/LibGfx/CMakeLists.txt | 1 + Tests/LibGfx/TestScalingFunctions.cpp | 66 +++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 Tests/LibGfx/TestScalingFunctions.cpp diff --git a/Tests/LibGfx/CMakeLists.txt b/Tests/LibGfx/CMakeLists.txt index b5b928039f..f86093f911 100644 --- a/Tests/LibGfx/CMakeLists.txt +++ b/Tests/LibGfx/CMakeLists.txt @@ -3,6 +3,7 @@ set(TEST_SOURCES TestFontHandling.cpp TestICCProfile.cpp TestImageDecoder.cpp + TestScalingFunctions.cpp ) foreach(source IN LISTS TEST_SOURCES) diff --git a/Tests/LibGfx/TestScalingFunctions.cpp b/Tests/LibGfx/TestScalingFunctions.cpp new file mode 100644 index 0000000000..1890c7fcd6 --- /dev/null +++ b/Tests/LibGfx/TestScalingFunctions.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2023, Tim Ledbetter + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +// Scaling modes which use linear interpolation should use premultiplied alpha. +// This prevents colors from changing hue unexpectedly when there is a change in opacity. +// This test uses an image that transitions from a completely opaque pixel in the top left to a completely transparent background. +// We ensure that premultipled alpha is used by checking that the RGB values of the interpolated pixels do not change, just the alpha values. +TEST_CASE(test_painter_scaling_uses_premultiplied_alpha) +{ + auto test_scaling_mode = [](auto scaling_mode) { + auto src_bitmap = MUST(Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, { 2, 2 })); + src_bitmap->fill(Color::Transparent); + src_bitmap->set_pixel({ 0, 0 }, Color::White); + + auto scaled_bitmap = MUST(Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, { 5, 5 })); + scaled_bitmap->fill(Color::Transparent); + + Gfx::Painter painter(scaled_bitmap); + painter.draw_scaled_bitmap(scaled_bitmap->rect(), src_bitmap, src_bitmap->rect(), 1.0f, scaling_mode); + + auto top_left_pixel = scaled_bitmap->get_pixel(0, 0); + EXPECT_EQ(top_left_pixel, Color::White); + + auto center_pixel = scaled_bitmap->get_pixel(scaled_bitmap->rect().center()); + EXPECT(center_pixel.alpha() > 0); + EXPECT(center_pixel.alpha() < 255); + EXPECT_EQ(center_pixel.with_alpha(0), Color(Color::White).with_alpha(0)); + + auto bottom_right_pixel = scaled_bitmap->get_pixel(scaled_bitmap->rect().bottom_right()); + EXPECT_EQ(bottom_right_pixel, Color::Transparent); + }; + + test_scaling_mode(Gfx::Painter::ScalingMode::BilinearBlend); + // FIXME: Include ScalingMode::SmoothPixels as part of this test + // This mode does not currently pass this test, as it behave according to the spec + // defined here: https://drafts.csswg.org/css-images/#valdef-image-rendering-pixelated + // test_scaling_mode(Gfx::Painter::ScalingMode::SmoothPixels); +} + +TEST_CASE(test_bitmap_scaling_uses_premultiplied_alpha) +{ + auto src_bitmap = MUST(Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, { 2, 2 })); + src_bitmap->fill(Color::Transparent); + src_bitmap->set_pixel({ 0, 0 }, Color::White); + + auto scaled_bitmap = MUST(src_bitmap->scaled(2.5f, 2.5f)); + EXPECT_EQ(scaled_bitmap->width(), 5); + EXPECT_EQ(scaled_bitmap->height(), 5); + auto top_left_pixel = scaled_bitmap->get_pixel(0, 0); + EXPECT_EQ(top_left_pixel, Color::White); + + auto center_pixel = scaled_bitmap->get_pixel(scaled_bitmap->rect().center()); + EXPECT(center_pixel.alpha() > 0); + EXPECT(center_pixel.alpha() < 255); + EXPECT_EQ(center_pixel.with_alpha(0), Color(Color::White).with_alpha(0)); + + auto bottom_right_pixel = scaled_bitmap->get_pixel(scaled_bitmap->rect().bottom_right()); + EXPECT_EQ(bottom_right_pixel, Color::Transparent); +}