chromium/third_party/blink/renderer/core/animation/css_scrollbar_color_interpolation_type_test.cc

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <memory>
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/animation/css_color_interpolation_type.h"
#include "third_party/blink/renderer/core/animation/interpolable_color.h"
#include "third_party/blink/renderer/core/animation/interpolable_value.h"
#include "third_party/blink/renderer/platform/graphics/color.h"

namespace blink {

TEST(CSSScrollbarColorInterpolationTypeTest, GetRGBA1) {
  Color color(230, 120, 0, 255);
  EXPECT_EQ(color,
            CSSColorInterpolationType::GetColor(
                *CSSColorInterpolationType::CreateInterpolableColor(color)));
}

TEST(CSSScrollbarColorInterpolationTypeTest, GetRGBA2) {
  Color color(100, 190, 0, 1);
  EXPECT_EQ(color,
            CSSColorInterpolationType::GetColor(
                *CSSColorInterpolationType::CreateInterpolableColor(color)));
}

TEST(CSSScrollbarColorInterpolationTypeTest, GetRGBA3) {
  Color color(35, 140, 10, 10);
  EXPECT_EQ(color,
            CSSColorInterpolationType::GetColor(
                *CSSColorInterpolationType::CreateInterpolableColor(color)));
}

TEST(CSSScrollbarColorInterpolationTypeTest, GetRGBA4) {
  Color color(35, 140, 10, 0);
  EXPECT_EQ(Color::FromRGBA(0, 0, 0, 0),
            CSSColorInterpolationType::GetColor(
                *CSSColorInterpolationType::CreateInterpolableColor(color)));
}

TEST(CSSScrollbarColorInterpolationTypeTest, RGBBounds) {
  Color from_color(0, 0, 0, 0);
  Color to_color(255, 255, 255, 255);
  std::unique_ptr<InterpolableValue> from =
      CSSColorInterpolationType::CreateInterpolableColor(from_color);
  std::unique_ptr<InterpolableValue> to =
      CSSColorInterpolationType::CreateInterpolableColor(to_color);
  std::unique_ptr<InterpolableValue> result =
      CSSColorInterpolationType::CreateInterpolableColor(to_color);

  from->Interpolate(*to, 1e30, *result);
  Color rgba = CSSColorInterpolationType::GetColor(*result);
  ASSERT_EQ(255, rgba.Red());
  ASSERT_EQ(255, rgba.Green());
  ASSERT_EQ(255, rgba.Blue());
  ASSERT_EQ(255, rgba.AlphaAsInteger());
}

TEST(CSSScrollbarColorInterpolationTypeTest, RGBToOklab) {
  Color from_color = Color::FromRGBAFloat(1, 1, 1, 1);
  Color to_color =
      Color::FromColorSpace(Color::ColorSpace::kOklab, 0, 0, 0, 0.5);
  std::unique_ptr<InterpolableColor> from =
      CSSColorInterpolationType::CreateInterpolableColor(from_color);
  std::unique_ptr<InterpolableColor> to =
      CSSColorInterpolationType::CreateInterpolableColor(to_color);

  from_color = CSSColorInterpolationType::GetColor(*from);
  ASSERT_EQ(Color::ColorSpace::kSRGBLegacy,
            from_color.GetColorInterpolationSpace());
  to_color = CSSColorInterpolationType::GetColor(*to);
  ASSERT_EQ(Color::ColorSpace::kOklab, to_color.GetColorInterpolationSpace());

  // This should make both color interpolations spaces oklab
  InterpolableColor::SetupColorInterpolationSpaces(*to, *from);

  from_color = CSSColorInterpolationType::GetColor(*from);
  ASSERT_EQ(Color::ColorSpace::kOklab, from_color.GetColorInterpolationSpace());
  to_color = CSSColorInterpolationType::GetColor(*to);
  ASSERT_EQ(Color::ColorSpace::kOklab, to_color.GetColorInterpolationSpace());
}

TEST(CSSScrollbarColorInterpolationTypeTest, Oklab) {
  Color from_color =
      Color::FromColorSpace(Color::ColorSpace::kOklab, 100, 1, 1, 1);
  Color to_color =
      Color::FromColorSpace(Color::ColorSpace::kOklab, 0, 0, 0, 0.5);
  std::unique_ptr<InterpolableValue> from =
      CSSColorInterpolationType::CreateInterpolableColor(from_color);
  std::unique_ptr<InterpolableValue> to =
      CSSColorInterpolationType::CreateInterpolableColor(to_color);
  std::unique_ptr<InterpolableValue> result =
      CSSColorInterpolationType::CreateInterpolableColor(to_color);

  Color result_color;
  from->Interpolate(*to, 0, *result);
  result_color = CSSColorInterpolationType::GetColor(*result);
  ASSERT_EQ(100, result_color.Param0());
  ASSERT_EQ(1, result_color.Param1());
  ASSERT_EQ(1, result_color.Param2());
  ASSERT_EQ(1, result_color.Alpha());
  ASSERT_EQ(Color::ColorSpace::kOklab,
            result_color.GetColorInterpolationSpace());

  from->Interpolate(*to, 0.5, *result);
  result_color = CSSColorInterpolationType::GetColor(*result);
  // Everything is premultiplied.
  ASSERT_EQ(50, result_color.Param0() * result_color.Alpha());
  ASSERT_EQ(0.5, result_color.Param1() * result_color.Alpha());
  ASSERT_EQ(0.5, result_color.Param2() * result_color.Alpha());
  ASSERT_EQ(0.75, result_color.Alpha());
  ASSERT_EQ(Color::ColorSpace::kOklab,
            result_color.GetColorInterpolationSpace());

  from->Interpolate(*to, 0.75, *result);
  result_color = CSSColorInterpolationType::GetColor(*result);
  // Everything is premultiplied.
  ASSERT_EQ(25, result_color.Param0() * result_color.Alpha());
  ASSERT_EQ(0.25, result_color.Param1() * result_color.Alpha());
  ASSERT_EQ(0.25, result_color.Param2() * result_color.Alpha());
  ASSERT_EQ(0.625, result_color.Alpha());
  ASSERT_EQ(Color::ColorSpace::kOklab,
            result_color.GetColorInterpolationSpace());

  from->Interpolate(*to, 1, *result);
  result_color = CSSColorInterpolationType::GetColor(*result);
  ASSERT_EQ(0, result_color.Param0());
  ASSERT_EQ(0, result_color.Param1());
  ASSERT_EQ(0, result_color.Param2());
  ASSERT_EQ(0.5, result_color.Alpha());
  ASSERT_EQ(Color::ColorSpace::kOklab,
            result_color.GetColorInterpolationSpace());
}

}  // namespace blink