diff --git a/impeller/geometry/color.h b/impeller/geometry/color.h index 8f5a83885e1b9..ad324e7fd55b3 100644 --- a/impeller/geometry/color.h +++ b/impeller/geometry/color.h @@ -49,6 +49,17 @@ struct Color { alpha == c.alpha; } + constexpr Color Premultiply() const { + return {red * alpha, green * alpha, blue * alpha, alpha}; + } + + constexpr Color Unpremultiply() const { + if (ScalarNearlyEqual(alpha, 0.0)) { + return Color::BlackTransparent(); + } + return {red / alpha, green / alpha, blue / alpha, alpha}; + } + static constexpr Color White() { return {1.0, 1.0, 1.0, 1.0}; } static constexpr Color Black() { return {0.0, 0.0, 0.0, 1.0}; } diff --git a/impeller/geometry/geometry_unittests.cc b/impeller/geometry/geometry_unittests.cc index 8299c45eb4873..3ec5d5ab99211 100644 --- a/impeller/geometry/geometry_unittests.cc +++ b/impeller/geometry/geometry_unittests.cc @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include #include "impeller/geometry/geometry_unittests.h" #include #include "flutter/testing/testing.h" @@ -568,6 +567,29 @@ TEST(GeometryTest, PointReflect) { } } +TEST(GeometryTest, ColorPremultiply) { + { + Color a(1.0, 0.5, 0.2, 0.5); + Color premultiplied = a.Premultiply(); + Color expected = Color(0.5, 0.25, 0.1, 0.5); + ASSERT_COLOR_NEAR(premultiplied, expected); + } + + { + Color a(0.5, 0.25, 0.1, 0.5); + Color unpremultiplied = a.Unpremultiply(); + Color expected = Color(1.0, 0.5, 0.2, 0.5); + ASSERT_COLOR_NEAR(unpremultiplied, expected); + } + + { + Color a(0.5, 0.25, 0.1, 0.0); + Color unpremultiplied = a.Unpremultiply(); + Color expected = Color(0.0, 0.0, 0.0, 0.0); + ASSERT_COLOR_NEAR(unpremultiplied, expected); + } +} + TEST(GeometryTest, CanConvertBetweenDegressAndRadians) { { auto deg = Degrees{90.0}; diff --git a/impeller/geometry/geometry_unittests.h b/impeller/geometry/geometry_unittests.h index 746df49df6075..61502f1b38dbe 100644 --- a/impeller/geometry/geometry_unittests.h +++ b/impeller/geometry/geometry_unittests.h @@ -58,6 +58,15 @@ inline ::testing::AssertionResult RectNear(impeller::Rect a, impeller::Rect b) { : ::testing::AssertionFailure() << "Rects are not equal."; } +inline ::testing::AssertionResult ColorNear(impeller::Color a, + impeller::Color b) { + auto equal = NumberNear(a.red, b.red) && NumberNear(a.green, b.green) && + NumberNear(a.blue, b.blue) && NumberNear(a.alpha, b.alpha); + + return equal ? ::testing::AssertionSuccess() + : ::testing::AssertionFailure() << "Colors are not equal."; +} + inline ::testing::AssertionResult PointNear(impeller::Point a, impeller::Point b) { auto equal = NumberNear(a.x, b.x) && NumberNear(a.y, b.y); @@ -76,5 +85,6 @@ inline ::testing::AssertionResult SizeNear(impeller::Size a, impeller::Size b) { #define ASSERT_MATRIX_NEAR(a, b) ASSERT_PRED2(&::MatrixNear, a, b) #define ASSERT_QUATERNION_NEAR(a, b) ASSERT_PRED2(&::QuaternionNear, a, b) #define ASSERT_RECT_NEAR(a, b) ASSERT_PRED2(&::RectNear, a, b) +#define ASSERT_COLOR_NEAR(a, b) ASSERT_PRED2(&::ColorNear, a, b) #define ASSERT_POINT_NEAR(a, b) ASSERT_PRED2(&::PointNear, a, b) #define ASSERT_SIZE_NEAR(a, b) ASSERT_PRED2(&::SizeNear, a, b)