chromium/ash/ambient/ui/ambient_animation_resizer_unittest.cc

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

#include "ash/ambient/ui/ambient_animation_resizer.h"

#include <memory>

#include "base/logging.h"
#include "cc/test/skia_common.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/geometry/vector2d.h"
#include "ui/lottie/animation.h"
#include "ui/views/border.h"
#include "ui/views/controls/animated_image_view.h"

namespace ash {
namespace {

using ::testing::Eq;

std::unique_ptr<views::AnimatedImageView> CreateAnimatedImageView(
    const gfx::Size& animation_size,
    const gfx::Rect& view_bounds) {
  auto view = std::make_unique<views::AnimatedImageView>();
  view->SetAnimatedImage(std::make_unique<lottie::Animation>(
      cc::CreateSkottie(animation_size,
                        /*duration_secs=*/1)));
  view->SetBoundsRect(view_bounds);
  return view;
}

}  // namespace

TEST(AmbientAnimationResizerTest, LandscapeScalesDownWidthAndCropsHeight) {
  auto view =
      CreateAnimatedImageView(gfx::Size(2000, 1500), gfx::Rect(1000, 600));
  AmbientAnimationResizer::Resize(*view);
  EXPECT_THAT(view->GetImageBounds(), Eq(gfx::Rect(0, -75, 1000, 750)));
}

TEST(AmbientAnimationResizerTest,
     LandscapeScalesDownWidthAndCropsHeightWithInsets) {
  auto view =
      CreateAnimatedImageView(gfx::Size(2000, 1500), gfx::Rect(1000, 600));
  // Content bounds are 500 x 300.
  view->SetBorder(views::CreateEmptyBorder(gfx::Insets::VH(150, 250)));
  AmbientAnimationResizer::Resize(*view);
  EXPECT_TRUE(view->GetImageBounds().ApproximatelyEqual(
      gfx::Rect(250, 150 - (75 / 2), 500, 375), /*tolerance=*/1));
}

TEST(AmbientAnimationResizerTest, LandscapeScalesDownWidthAndHeight) {
  auto view =
      CreateAnimatedImageView(gfx::Size(2000, 1500), gfx::Rect(1000, 750));
  AmbientAnimationResizer::Resize(*view);
  EXPECT_THAT(view->GetImageBounds(), Eq(gfx::Rect(0, 0, 1000, 750)));
}

TEST(AmbientAnimationResizerTest,
     LandscapeScalesDownWidthAndDoesNotCropHeight) {
  auto view =
      CreateAnimatedImageView(gfx::Size(2000, 1500), gfx::Rect(1000, 800));
  AmbientAnimationResizer::Resize(*view);
  EXPECT_THAT(view->GetImageBounds(), Eq(gfx::Rect(0, 25, 1000, 750)));
}

TEST(AmbientAnimationResizerTest, LandscapeScalesUpByWidth) {
  auto view =
      CreateAnimatedImageView(gfx::Size(2000, 1500), gfx::Rect(2500, 1500));
  AmbientAnimationResizer::Resize(*view);
  EXPECT_TRUE(view->GetImageBounds().ApproximatelyEqual(
      gfx::Rect(0, -(375 / 2), 2500, 1875), /*tolerance=*/1));
}

TEST(AmbientAnimationResizerTest, LandscapeAppliesJitter) {
  auto view =
      CreateAnimatedImageView(gfx::Size(2000, 1500), gfx::Rect(1000, 600));
  AmbientAnimationResizer::Resize(*view, /*padding_for_jitter=*/10);
  // New Height: 1500 * (1020 / 2000) = 765
  // New Y origin: -(765 - 600) / 2 = 82.5
  EXPECT_THAT(view->GetImageBounds(), Eq(gfx::Rect(-10, -82, 1020, 765)));
}

TEST(AmbientAnimationResizerTest, PortraitScalesDownWidthAndCropsHeight) {
  auto view =
      CreateAnimatedImageView(gfx::Size(1500, 2000), gfx::Rect(750, 1200));
  AmbientAnimationResizer::Resize(*view);
  EXPECT_THAT(view->GetImageBounds(), Eq(gfx::Rect(0, 100, 750, 1000)));
}

TEST(AmbientAnimationResizerTest,
     PortraitScalesDownWidthAndCropsHeightWithInsets) {
  auto view =
      CreateAnimatedImageView(gfx::Size(1500, 2000), gfx::Rect(600, 1000));
  // Content bounds are 300 x 500.
  view->SetBorder(views::CreateEmptyBorder(gfx::Insets::VH(250, 150)));
  AmbientAnimationResizer::Resize(*view);
  EXPECT_TRUE(view->GetImageBounds().ApproximatelyEqual(
      gfx::Rect(150, 250 + (500 - 400) / 2, 300, 400), /*tolerance=*/1));
}

TEST(AmbientAnimationResizerTest, PortraitScalesDownWidthAndHeight) {
  auto view =
      CreateAnimatedImageView(gfx::Size(1500, 2000), gfx::Rect(750, 1000));
  AmbientAnimationResizer::Resize(*view);
  EXPECT_THAT(view->GetImageBounds(), Eq(gfx::Rect(0, 0, 750, 1000)));
}

TEST(AmbientAnimationResizerTest, PortraitScalesDownWidthAndDoesNotCropHeight) {
  auto view =
      CreateAnimatedImageView(gfx::Size(1500, 2000), gfx::Rect(600, 1000));
  AmbientAnimationResizer::Resize(*view);
  // Scaled height = 2000 / (1500 / 600) = 800
  // Image y offset = (1000 - 800) / 2 = 100
  EXPECT_THAT(view->GetImageBounds(), Eq(gfx::Rect(0, 100, 600, 800)));
}

TEST(AmbientAnimationResizerTest, PortraitScalesUpByWidth) {
  auto view =
      CreateAnimatedImageView(gfx::Size(1500, 2000), gfx::Rect(1800, 2000));
  AmbientAnimationResizer::Resize(*view);
  EXPECT_TRUE(view->GetImageBounds().ApproximatelyEqual(
      gfx::Rect(0, -200, 1800, 2400), /*tolerance=*/1));
}

TEST(AmbientAnimationResizerTest, PortraitAppliesJitter) {
  auto view =
      CreateAnimatedImageView(gfx::Size(1500, 2000), gfx::Rect(600, 1000));
  AmbientAnimationResizer::Resize(*view, /*padding_for_jitter=*/10);
  // New Height: 2000 * (620 / 1500) = 826 2/3
  // New Y origin: -(1000 - 827) / 2 = 86.5
  EXPECT_TRUE(view->GetImageBounds().ApproximatelyEqual(
      gfx::Rect(-10, 87, 620, 827), /*tolerance=*/1));
}

}  // namespace ash