#include "paint_renderer/compositor.h" #include "test_harness.h" #include #include using pp::foundation::StatusCode; using pp::paint::BlendMode; using pp::paint::Rgba; using pp::paint_renderer::LayerCompositeView; using pp::paint_renderer::composite_layer; using pp::renderer::Extent2D; namespace { bool near(float a, float b) { return std::fabs(a - b) < 0.0001F; } void composites_visible_layer_with_opacity(pp::tests::Harness& h) { std::vector destination { Rgba { .r = 0.2F, .g = 0.4F, .b = 0.6F, .a = 0.5F }, }; const std::vector foreground { Rgba { .r = 0.8F, .g = 0.2F, .b = 0.1F, .a = 0.5F }, }; const auto status = composite_layer( destination, Extent2D { .width = 1, .height = 1 }, LayerCompositeView { .pixels = foreground, .opacity = 0.5F, .visible = true, .blend_mode = BlendMode::normal, }); PP_EXPECT(h, status.ok()); PP_EXPECT(h, near(destination[0].a, 0.625F)); PP_EXPECT(h, near(destination[0].r, 0.44F)); PP_EXPECT(h, near(destination[0].g, 0.32F)); PP_EXPECT(h, near(destination[0].b, 0.4F)); } void invisible_and_zero_opacity_layers_are_noops(pp::tests::Harness& h) { const Rgba original { .r = 0.1F, .g = 0.2F, .b = 0.3F, .a = 0.4F }; std::vector destination { original }; const std::vector foreground { Rgba { .r = 1.0F, .g = 1.0F, .b = 1.0F, .a = 1.0F }, }; PP_EXPECT(h, composite_layer( destination, Extent2D { .width = 1, .height = 1 }, LayerCompositeView { .pixels = foreground, .opacity = 1.0F, .visible = false }).ok()); PP_EXPECT(h, near(destination[0].r, original.r)); PP_EXPECT(h, near(destination[0].g, original.g)); PP_EXPECT(h, near(destination[0].b, original.b)); PP_EXPECT(h, near(destination[0].a, original.a)); PP_EXPECT(h, composite_layer( destination, Extent2D { .width = 1, .height = 1 }, LayerCompositeView { .pixels = foreground, .opacity = 0.0F, .visible = true }).ok()); PP_EXPECT(h, near(destination[0].r, original.r)); PP_EXPECT(h, near(destination[0].g, original.g)); PP_EXPECT(h, near(destination[0].b, original.b)); PP_EXPECT(h, near(destination[0].a, original.a)); } void rejects_invalid_sizes_and_opacity(pp::tests::Harness& h) { std::vector destination(2); const std::vector foreground(1); const auto mismatched = composite_layer( destination, Extent2D { .width = 2, .height = 1 }, LayerCompositeView { .pixels = foreground }); const auto bad_opacity = composite_layer( destination, Extent2D { .width = 2, .height = 1 }, LayerCompositeView { .pixels = destination, .opacity = 1.5F }); const auto bad_extent = composite_layer( destination, Extent2D { .width = 0, .height = 1 }, LayerCompositeView { .pixels = destination }); PP_EXPECT(h, !mismatched.ok()); PP_EXPECT(h, mismatched.code == StatusCode::invalid_argument); PP_EXPECT(h, !bad_opacity.ok()); PP_EXPECT(h, bad_opacity.code == StatusCode::out_of_range); PP_EXPECT(h, !bad_extent.ok()); PP_EXPECT(h, bad_extent.code == StatusCode::invalid_argument); } } int main() { pp::tests::Harness harness; harness.run("composites_visible_layer_with_opacity", composites_visible_layer_with_opacity); harness.run("invisible_and_zero_opacity_layers_are_noops", invisible_and_zero_opacity_layers_are_noops); harness.run("rejects_invalid_sizes_and_opacity", rejects_invalid_sizes_and_opacity); return harness.finish(); }