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

#include "cc/layers/layer_utils.h"

#include "cc/animation/animation_host.h"
#include "cc/animation/animation_id_provider.h"
#include "cc/animation/transform_operations.h"
#include "cc/layers/layer_impl.h"
#include "cc/test/animation_test_common.h"
#include "cc/test/fake_impl_task_runner_provider.h"
#include "cc/test/fake_layer_tree_host_impl.h"
#include "cc/test/test_shared_bitmap_manager.h"
#include "cc/test/test_task_graph_runner.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/box_f.h"
#include "ui/gfx/test/gfx_util.h"

namespace cc {
namespace {

float diagonal(float width, float height) {
  return std::sqrt(width * width + height * height);
}

class LayerTreeSettingsForAnimationBoundsTest : public LayerTreeSettings {
 public:
  LayerTreeSettingsForAnimationBoundsTest() {
    use_compositor_animation_timelines = true;
  }
};

class LayerUtilsGetAnimationBoundsTest : public testing::Test {
 public:
  LayerUtilsGetAnimationBoundsTest()
      : host_impl_(LayerTreeSettingsForAnimationBoundsTest(),
                   &task_runner_provider_,
                   &shared_bitmap_manager_,
                   &task_graph_runner_),
        root_(CreateThreeNodeTree(&host_impl_)),
        parent_(root_->children()[0].get()),
        child_(parent_->children()[0].get()) {
    if (host_impl_.settings().use_compositor_animation_timelines) {
      timeline_ =
          AnimationTimeline::Create(AnimationIdProvider::NextTimelineId());
      host_impl_.animation_host()->AddAnimationTimeline(timeline_);
    }
  }

  LayerImpl* root() { return root_.get(); }
  LayerImpl* parent() { return parent_; }
  LayerImpl* child() { return child_; }
  scoped_refptr<AnimationTimeline> timeline() { return timeline_; }
  FakeLayerTreeHostImpl& host_impl() { return host_impl_; }

 private:
  static scoped_ptr<LayerImpl> CreateThreeNodeTree(
      LayerTreeHostImpl* host_impl) {
    scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl->active_tree(), 1);
    root->AddChild(LayerImpl::Create(host_impl->active_tree(), 2));
    root->children()[0]->AddChild(
        LayerImpl::Create(host_impl->active_tree(), 3));
    return root;
  }

  FakeImplTaskRunnerProvider task_runner_provider_;
  TestSharedBitmapManager shared_bitmap_manager_;
  TestTaskGraphRunner task_graph_runner_;
  FakeLayerTreeHostImpl host_impl_;
  scoped_ptr<LayerImpl> root_;
  LayerImpl* parent_;
  LayerImpl* child_;
  scoped_refptr<AnimationTimeline> timeline_;
};

TEST_F(LayerUtilsGetAnimationBoundsTest, ScaleRoot) {
  double duration = 1.0;

  TransformOperations start;
  start.AppendScale(1.f, 1.f, 1.f);
  TransformOperations end;
  end.AppendScale(2.f, 2.f, 1.f);
  if (host_impl().settings().use_compositor_animation_timelines) {
    AddAnimatedTransformToLayerWithPlayer(root()->id(), timeline(), duration,
                                          start, end);
  } else {
    AddAnimatedTransformToLayer(root(), duration, start, end);
  }

  root()->SetPosition(gfx::PointF());
  parent()->SetPosition(gfx::PointF());
  parent()->SetBounds(gfx::Size(350, 200));

  child()->SetDrawsContent(true);
  child()->draw_properties().screen_space_transform_is_animating = true;
  child()->SetPosition(gfx::PointF(150.f, 50.f));
  child()->SetBounds(gfx::Size(100, 200));

  gfx::BoxF box;
  bool success = LayerUtils::GetAnimationBounds(*child(), &box);
  EXPECT_TRUE(success);
  gfx::BoxF expected(150.f, 50.f, 0.f, 350.f, 450.f, 0.f);
  EXPECT_BOXF_EQ(expected, box);
}

TEST_F(LayerUtilsGetAnimationBoundsTest, TranslateParentLayer) {
  double duration = 1.0;

  TransformOperations start;
  start.AppendTranslate(0.f, 0.f, 0.f);
  TransformOperations end;
  end.AppendTranslate(50.f, 50.f, 0.f);
  if (host_impl().settings().use_compositor_animation_timelines) {
    AddAnimatedTransformToLayerWithPlayer(parent()->id(), timeline(), duration,
                                          start, end);
  } else {
    AddAnimatedTransformToLayer(parent(), duration, start, end);
  }

  parent()->SetBounds(gfx::Size(350, 200));

  child()->SetDrawsContent(true);
  child()->draw_properties().screen_space_transform_is_animating = true;
  child()->SetPosition(gfx::PointF(150.f, 50.f));
  child()->SetBounds(gfx::Size(100, 200));

  gfx::BoxF box;
  bool success = LayerUtils::GetAnimationBounds(*child(), &box);
  EXPECT_TRUE(success);
  gfx::BoxF expected(150.f, 50.f, 0.f, 150.f, 250.f, 0.f);
  EXPECT_BOXF_EQ(expected, box);
}

TEST_F(LayerUtilsGetAnimationBoundsTest, TranslateChildLayer) {
  double duration = 1.0;

  TransformOperations start;
  start.AppendTranslate(0.f, 0.f, 0.f);
  TransformOperations end;
  end.AppendTranslate(50.f, 50.f, 0.f);
  if (host_impl().settings().use_compositor_animation_timelines) {
    AddAnimatedTransformToLayerWithPlayer(child()->id(), timeline(), duration,
                                          start, end);
  } else {
    AddAnimatedTransformToLayer(child(), duration, start, end);
  }

  parent()->SetBounds(gfx::Size(350, 200));

  child()->SetDrawsContent(true);
  child()->draw_properties().screen_space_transform_is_animating = true;
  child()->SetPosition(gfx::PointF(150.f, 50.f));
  child()->SetBounds(gfx::Size(100, 200));

  gfx::BoxF box;
  bool success = LayerUtils::GetAnimationBounds(*child(), &box);
  EXPECT_TRUE(success);
  gfx::BoxF expected(150.f, 50.f, 0.f, 150.f, 250.f, 0.f);
  EXPECT_BOXF_EQ(expected, box);
}

TEST_F(LayerUtilsGetAnimationBoundsTest, TranslateBothLayers) {
  double duration = 1.0;

  TransformOperations start;
  start.AppendTranslate(0.f, 0.f, 0.f);
  TransformOperations child_end;
  child_end.AppendTranslate(50.f, 0.f, 0.f);
  if (host_impl().settings().use_compositor_animation_timelines) {
    AddAnimatedTransformToLayerWithPlayer(parent()->id(), timeline(), duration,
                                          start, child_end);
  } else {
    AddAnimatedTransformToLayer(parent(), duration, start, child_end);
  }

  TransformOperations grand_child_end;
  grand_child_end.AppendTranslate(0.f, 50.f, 0.f);
  if (host_impl().settings().use_compositor_animation_timelines) {
    AddAnimatedTransformToLayerWithPlayer(child()->id(), timeline(), duration,
                                          start, grand_child_end);
  } else {
    AddAnimatedTransformToLayer(child(), duration, start, grand_child_end);
  }

  parent()->SetBounds(gfx::Size(350, 200));

  child()->SetDrawsContent(true);
  child()->draw_properties().screen_space_transform_is_animating = true;
  child()->SetPosition(gfx::PointF(150.f, 50.f));
  child()->SetBounds(gfx::Size(100, 200));

  gfx::BoxF box;
  bool success = LayerUtils::GetAnimationBounds(*child(), &box);
  EXPECT_TRUE(success);
  gfx::BoxF expected(150.f, 50.f, 0.f, 150.f, 250.f, 0.f);
  EXPECT_BOXF_EQ(expected, box);
}

TEST_F(LayerUtilsGetAnimationBoundsTest, RotateXNoPerspective) {
  double duration = 1.0;

  TransformOperations start;
  start.AppendRotate(1.f, 0.f, 0.f, 0.f);
  TransformOperations end;
  end.AppendRotate(1.f, 0.f, 0.f, 90.f);
  if (host_impl().settings().use_compositor_animation_timelines) {
    AddAnimatedTransformToLayerWithPlayer(child()->id(), timeline(), duration,
                                          start, end);
  } else {
    AddAnimatedTransformToLayer(child(), duration, start, end);
  }

  parent()->SetBounds(gfx::Size(350, 200));

  gfx::Size bounds(100, 100);
  child()->SetDrawsContent(true);
  child()->draw_properties().screen_space_transform_is_animating = true;
  child()->SetPosition(gfx::PointF(150.f, 50.f));
  child()->SetBounds(bounds);
  child()->SetTransformOrigin(
      gfx::Point3F(bounds.width() * 0.5f, bounds.height() * 0.5f, 0));

  gfx::BoxF box;
  bool success = LayerUtils::GetAnimationBounds(*child(), &box);
  EXPECT_TRUE(success);
  gfx::BoxF expected(150.f, 50.f, -50.f, 100.f, 100.f, 100.f);
  EXPECT_BOXF_EQ(expected, box);
}

TEST_F(LayerUtilsGetAnimationBoundsTest, RotateXWithPerspective) {
  double duration = 1.0;

  TransformOperations start;
  start.AppendRotate(1.f, 0.f, 0.f, 0.f);
  TransformOperations end;
  end.AppendRotate(1.f, 0.f, 0.f, 90.f);
  if (host_impl().settings().use_compositor_animation_timelines) {
    AddAnimatedTransformToLayerWithPlayer(child()->id(), timeline(), duration,
                                          start, end);
  } else {
    AddAnimatedTransformToLayer(child(), duration, start, end);
  }

  // Make the anchor point not the default 0.5 value and line up with the
  // child center to make the math easier.
  parent()->SetTransformOrigin(
      gfx::Point3F(0.375f * 400.f, 0.375f * 400.f, 0.f));
  parent()->SetBounds(gfx::Size(400, 400));

  gfx::Transform perspective;
  perspective.ApplyPerspectiveDepth(100.f);
  parent()->SetTransform(perspective);

  gfx::Size bounds(100, 100);
  child()->SetDrawsContent(true);
  child()->draw_properties().screen_space_transform_is_animating = true;
  child()->SetPosition(gfx::PointF(100.f, 100.f));
  child()->SetBounds(bounds);
  child()->SetTransformOrigin(
      gfx::Point3F(bounds.width() * 0.5f, bounds.height() * 0.5f, 0));

  gfx::BoxF box;
  bool success = LayerUtils::GetAnimationBounds(*child(), &box);
  EXPECT_TRUE(success);
  gfx::BoxF expected(50.f, 50.f, -33.333336f, 200.f, 200.f, 133.333344f);
  EXPECT_BOXF_EQ(expected, box);
}

TEST_F(LayerUtilsGetAnimationBoundsTest, RotateZ) {
  double duration = 1.0;

  TransformOperations start;
  start.AppendRotate(0.f, 0.f, 1.f, 0.f);
  TransformOperations end;
  end.AppendRotate(0.f, 0.f, 1.f, 90.f);
  if (host_impl().settings().use_compositor_animation_timelines) {
    AddAnimatedTransformToLayerWithPlayer(child()->id(), timeline(), duration,
                                          start, end);
  } else {
    AddAnimatedTransformToLayer(child(), duration, start, end);
  }

  parent()->SetBounds(gfx::Size(350, 200));

  gfx::Size bounds(100, 100);
  child()->SetDrawsContent(true);
  child()->draw_properties().screen_space_transform_is_animating = true;
  child()->SetPosition(gfx::PointF(150.f, 50.f));
  child()->SetBounds(bounds);
  child()->SetTransformOrigin(
      gfx::Point3F(bounds.width() * 0.5f, bounds.height() * 0.5f, 0));

  gfx::BoxF box;
  bool success = LayerUtils::GetAnimationBounds(*child(), &box);
  EXPECT_TRUE(success);
  float diag = diagonal(bounds.width(), bounds.height());
  gfx::BoxF expected(150.f + 0.5f * (bounds.width() - diag),
                     50.f + 0.5f * (bounds.height() - diag),
                     0.f,
                     diag,
                     diag,
                     0.f);
  EXPECT_BOXF_EQ(expected, box);
}

TEST_F(LayerUtilsGetAnimationBoundsTest, MismatchedTransforms) {
  double duration = 1.0;

  TransformOperations start;
  start.AppendTranslate(5, 6, 7);
  TransformOperations end;
  end.AppendRotate(0.f, 0.f, 1.f, 90.f);
  if (host_impl().settings().use_compositor_animation_timelines) {
    AddAnimatedTransformToLayerWithPlayer(child()->id(), timeline(), duration,
                                          start, end);
  } else {
    AddAnimatedTransformToLayer(child(), duration, start, end);
  }

  parent()->SetBounds(gfx::Size(350, 200));

  gfx::Size bounds(100, 100);
  child()->SetDrawsContent(true);
  child()->draw_properties().screen_space_transform_is_animating = true;
  child()->SetPosition(gfx::PointF(150.f, 50.f));
  child()->SetBounds(bounds);

  gfx::BoxF box;
  bool success = LayerUtils::GetAnimationBounds(*child(), &box);
  EXPECT_FALSE(success);
}

}  // namespace
}  // namespace cc
