Add paint blend reference tests
This commit is contained in:
105
tests/paint/blend_tests.cpp
Normal file
105
tests/paint/blend_tests.cpp
Normal file
@@ -0,0 +1,105 @@
|
||||
#include "paint/blend.h"
|
||||
#include "test_harness.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <string_view>
|
||||
|
||||
using pp::paint::BlendMode;
|
||||
using pp::paint::Rgba;
|
||||
using pp::paint::blend_mode_name;
|
||||
using pp::paint::blend_pixels;
|
||||
|
||||
namespace {
|
||||
|
||||
bool near(float a, float b)
|
||||
{
|
||||
return std::fabs(a - b) < 0.0001F;
|
||||
}
|
||||
|
||||
void normal_blend_matches_source_over_alpha(pp::tests::Harness& h)
|
||||
{
|
||||
const auto result = blend_pixels(
|
||||
Rgba { .r = 0.2F, .g = 0.4F, .b = 0.6F, .a = 0.5F },
|
||||
Rgba { .r = 0.8F, .g = 0.2F, .b = 0.1F, .a = 0.25F },
|
||||
BlendMode::normal);
|
||||
|
||||
PP_EXPECT(h, near(result.a, 0.625F));
|
||||
PP_EXPECT(h, near(result.r, 0.44F));
|
||||
PP_EXPECT(h, near(result.g, 0.32F));
|
||||
PP_EXPECT(h, near(result.b, 0.4F));
|
||||
}
|
||||
|
||||
void zero_alpha_stroke_leaves_base_unchanged(pp::tests::Harness& h)
|
||||
{
|
||||
const Rgba base { .r = 0.2F, .g = 0.3F, .b = 0.4F, .a = 0.5F };
|
||||
const auto result = blend_pixels(
|
||||
base,
|
||||
Rgba { .r = 1.0F, .g = 1.0F, .b = 1.0F, .a = 0.0F },
|
||||
BlendMode::screen);
|
||||
|
||||
PP_EXPECT(h, near(result.r, base.r));
|
||||
PP_EXPECT(h, near(result.g, base.g));
|
||||
PP_EXPECT(h, near(result.b, base.b));
|
||||
PP_EXPECT(h, near(result.a, base.a));
|
||||
}
|
||||
|
||||
void multiply_and_screen_are_bounded(pp::tests::Harness& h)
|
||||
{
|
||||
const Rgba base { .r = 0.25F, .g = 0.5F, .b = 0.75F, .a = 1.0F };
|
||||
const Rgba stroke { .r = 0.5F, .g = 0.5F, .b = 0.5F, .a = 1.0F };
|
||||
const auto multiply = blend_pixels(base, stroke, BlendMode::multiply);
|
||||
const auto screen = blend_pixels(base, stroke, BlendMode::screen);
|
||||
|
||||
PP_EXPECT(h, near(multiply.r, 0.125F));
|
||||
PP_EXPECT(h, near(multiply.g, 0.25F));
|
||||
PP_EXPECT(h, near(multiply.b, 0.375F));
|
||||
PP_EXPECT(h, near(screen.r, 0.625F));
|
||||
PP_EXPECT(h, near(screen.g, 0.75F));
|
||||
PP_EXPECT(h, near(screen.b, 0.875F));
|
||||
}
|
||||
|
||||
void color_dodge_and_overlay_handle_extremes(pp::tests::Harness& h)
|
||||
{
|
||||
const auto dodge = blend_pixels(
|
||||
Rgba { .r = 0.4F, .g = 0.5F, .b = 0.6F, .a = 1.0F },
|
||||
Rgba { .r = 1.0F, .g = 0.5F, .b = 0.0F, .a = 1.0F },
|
||||
BlendMode::color_dodge);
|
||||
const auto overlay = blend_pixels(
|
||||
Rgba { .r = 0.25F, .g = 0.5F, .b = 0.75F, .a = 1.0F },
|
||||
Rgba { .r = 0.5F, .g = 0.5F, .b = 0.5F, .a = 1.0F },
|
||||
BlendMode::overlay);
|
||||
|
||||
PP_EXPECT(h, near(dodge.r, 1.0F));
|
||||
PP_EXPECT(h, near(dodge.g, 1.0F));
|
||||
PP_EXPECT(h, near(dodge.b, 0.6F));
|
||||
PP_EXPECT(h, near(overlay.r, 0.25F));
|
||||
PP_EXPECT(h, near(overlay.g, 0.5F));
|
||||
PP_EXPECT(h, near(overlay.b, 0.75F));
|
||||
}
|
||||
|
||||
void clamps_inputs_and_names_modes(pp::tests::Harness& h)
|
||||
{
|
||||
const auto result = blend_pixels(
|
||||
Rgba { .r = -1.0F, .g = 2.0F, .b = 0.5F, .a = 2.0F },
|
||||
Rgba { .r = 2.0F, .g = -1.0F, .b = 0.5F, .a = 2.0F },
|
||||
BlendMode::normal);
|
||||
|
||||
PP_EXPECT(h, near(result.r, 1.0F));
|
||||
PP_EXPECT(h, near(result.g, 0.0F));
|
||||
PP_EXPECT(h, near(result.b, 0.5F));
|
||||
PP_EXPECT(h, near(result.a, 1.0F));
|
||||
PP_EXPECT(h, blend_mode_name(BlendMode::overlay) == std::string_view("overlay"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
pp::tests::Harness harness;
|
||||
harness.run("normal_blend_matches_source_over_alpha", normal_blend_matches_source_over_alpha);
|
||||
harness.run("zero_alpha_stroke_leaves_base_unchanged", zero_alpha_stroke_leaves_base_unchanged);
|
||||
harness.run("multiply_and_screen_are_bounded", multiply_and_screen_are_bounded);
|
||||
harness.run("color_dodge_and_overlay_handle_extremes", color_dodge_and_overlay_handle_extremes);
|
||||
harness.run("clamps_inputs_and_names_modes", clamps_inputs_and_names_modes);
|
||||
return harness.finish();
|
||||
}
|
||||
Reference in New Issue
Block a user