// Copyright 2012 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 <stddef.h>

#include "cc/layers/append_quads_data.h"
#include "cc/layers/nine_patch_layer_impl.h"
#include "cc/resources/ui_resource_bitmap.h"
#include "cc/resources/ui_resource_client.h"
#include "cc/test/fake_impl_task_runner_provider.h"
#include "cc/test/fake_layer_tree_frame_sink.h"
#include "cc/test/fake_ui_resource_layer_tree_host_impl.h"
#include "cc/test/geometry_test_utils.h"
#include "cc/test/layer_test_common.h"
#include "cc/trees/single_thread_proxy.h"
#include "components/viz/common/quads/texture_draw_quad.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/safe_integer_conversions.h"
#include "ui/gfx/transform.h"

namespace cc {
namespace {

gfx::Rect ToRoundedIntRect(const gfx::RectF& rect_f) {
  return gfx::Rect(gfx::ToRoundedInt(rect_f.x()),
                   gfx::ToRoundedInt(rect_f.y()),
                   gfx::ToRoundedInt(rect_f.width()),
                   gfx::ToRoundedInt(rect_f.height()));
}

void NinePatchLayerLayoutTest(const gfx::Size& bitmap_size,
                              const gfx::Rect& aperture_rect,
                              const gfx::Size& layer_size,
                              const gfx::Rect& border,
                              bool fill_center,
                              size_t expected_quad_size) {
  std::unique_ptr<viz::RenderPass> render_pass = viz::RenderPass::Create();
  gfx::Rect visible_layer_rect(layer_size);
  gfx::Rect expected_remaining(border.x(), border.y(),
                               layer_size.width() - border.width(),
                               layer_size.height() - border.height());

  FakeImplTaskRunnerProvider task_runner_provider;
  TestTaskGraphRunner task_graph_runner;
  std::unique_ptr<LayerTreeFrameSink> layer_tree_frame_sink =
      FakeLayerTreeFrameSink::Create3d();
  FakeUIResourceLayerTreeHostImpl host_impl(&task_runner_provider,
                                            &task_graph_runner);
  host_impl.SetVisible(true);
  host_impl.InitializeRenderer(layer_tree_frame_sink.get());

  std::unique_ptr<NinePatchLayerImpl> layer =
      NinePatchLayerImpl::Create(host_impl.active_tree(), 1);
  layer->draw_properties().visible_layer_rect = visible_layer_rect;
  layer->SetBounds(layer_size);
  layer->test_properties()->force_render_surface = true;

  UIResourceId uid = 1;
  bool is_opaque = false;
  UIResourceBitmap bitmap(bitmap_size, is_opaque);

  host_impl.CreateUIResource(uid, bitmap);
  layer->SetUIResourceId(uid);
  layer->SetImageBounds(bitmap_size);
  layer->SetLayout(aperture_rect, border, gfx::Rect(), fill_center, false);
  host_impl.active_tree()->SetRootLayerForTesting(std::move(layer));
  host_impl.active_tree()->BuildPropertyTreesForTesting();

  AppendQuadsData data;
  host_impl.active_tree()->root_layer_for_testing()->AppendQuads(
      render_pass.get(), &data);

  // Verify quad rects
  const auto& quads = render_pass->quad_list;
  EXPECT_EQ(expected_quad_size, quads.size());

  Region layer_remaining(visible_layer_rect);
  for (auto iter = quads.cbegin(); iter != quads.cend(); ++iter) {
    gfx::Rect quad_rect = iter->rect;

    EXPECT_TRUE(visible_layer_rect.Contains(quad_rect)) << iter.index();
    EXPECT_TRUE(layer_remaining.Contains(quad_rect)) << iter.index();
    EXPECT_EQ(iter->needs_blending,
              !iter->shared_quad_state->are_contents_opaque);
    layer_remaining.Subtract(Region(quad_rect));
  }

  // Check if the left-over quad is the same size as the mapped aperture quad in
  // layer space.
  if (!fill_center) {
    EXPECT_EQ(expected_remaining, layer_remaining.bounds());
  } else {
    EXPECT_TRUE(layer_remaining.bounds().IsEmpty());
  }

  // Verify UV rects
  gfx::Rect bitmap_rect(bitmap_size);
  Region tex_remaining(bitmap_rect);
  for (auto* quad : quads) {
    const viz::TextureDrawQuad* tex_quad =
        viz::TextureDrawQuad::MaterialCast(quad);
    gfx::RectF tex_rect =
        gfx::BoundingRect(tex_quad->uv_top_left, tex_quad->uv_bottom_right);
    tex_rect.Scale(bitmap_size.width(), bitmap_size.height());
    tex_remaining.Subtract(Region(ToRoundedIntRect(tex_rect)));
  }

  if (!fill_center) {
    EXPECT_EQ(aperture_rect, tex_remaining.bounds());
    Region aperture_region(aperture_rect);
    EXPECT_EQ(aperture_region, tex_remaining);
  } else {
    EXPECT_TRUE(layer_remaining.bounds().IsEmpty());
  }
}

void NinePatchLayerLayoutTestWithOcclusion(const gfx::Size& bitmap_size,
                                           const gfx::Rect& aperture_rect,
                                           const gfx::Size& layer_size,
                                           const gfx::Rect& border,
                                           const gfx::Rect& occlusion,
                                           bool fill_center,
                                           size_t expected_quad_size) {
  std::unique_ptr<viz::RenderPass> render_pass = viz::RenderPass::Create();
  gfx::Rect visible_layer_rect(layer_size);
  int border_left = std::min(border.x(), occlusion.x()),
      border_top = std::min(border.y(), occlusion.y()),
      border_right = std::min(border.width() - border.x(),
                              layer_size.width() - occlusion.right()),
      border_bottom = std::min(border.height() - border.y(),
                               layer_size.height() - occlusion.bottom());
  gfx::Rect expected_layer_remaining(
      border_left, border_top, layer_size.width() - border_left - border_right,
      layer_size.height() - border_top - border_bottom);
  float ratio_left = border_left == 0 ? 0 : (aperture_rect.x() / border.x()),
        ratio_top = border_top == 0 ? 0 : (aperture_rect.y() / border.y()),
        ratio_right = border_right == 0
                          ? 0
                          : ((bitmap_size.width() - aperture_rect.right()) /
                             (border.width() - border.x())),
        ratio_bottom = border_bottom == 0
                           ? 0
                           : ((bitmap_size.height() - aperture_rect.bottom()) /
                              (border.height() - border.y()));
  int image_remaining_left = border_left * ratio_left,
      image_remaining_top = border_top * ratio_top,
      image_remaining_right = border_right * ratio_right,
      image_remaining_bottom = border_bottom * ratio_bottom;
  gfx::Rect expected_tex_remaining(
      image_remaining_left, image_remaining_top,
      bitmap_size.width() - image_remaining_right - image_remaining_left,
      bitmap_size.height() - image_remaining_bottom - image_remaining_top);

  FakeImplTaskRunnerProvider task_runner_provider;
  TestTaskGraphRunner task_graph_runner;
  std::unique_ptr<LayerTreeFrameSink> layer_tree_frame_sink =
      FakeLayerTreeFrameSink::Create3d();
  FakeUIResourceLayerTreeHostImpl host_impl(&task_runner_provider,
                                            &task_graph_runner);
  host_impl.SetVisible(true);
  host_impl.InitializeRenderer(layer_tree_frame_sink.get());

  std::unique_ptr<NinePatchLayerImpl> layer =
      NinePatchLayerImpl::Create(host_impl.active_tree(), 1);
  layer->draw_properties().visible_layer_rect = visible_layer_rect;
  layer->SetBounds(layer_size);
  layer->test_properties()->force_render_surface = true;

  UIResourceId uid = 1;
  bool is_opaque = false;
  UIResourceBitmap bitmap(bitmap_size, is_opaque);

  host_impl.CreateUIResource(uid, bitmap);
  layer->SetUIResourceId(uid);
  layer->SetImageBounds(bitmap_size);
  layer->SetLayout(aperture_rect, border, occlusion, false, false);
  host_impl.active_tree()->SetRootLayerForTesting(std::move(layer));
  host_impl.active_tree()->BuildPropertyTreesForTesting();

  AppendQuadsData data;
  host_impl.active_tree()->root_layer_for_testing()->AppendQuads(
      render_pass.get(), &data);

  // Verify quad rects
  const auto& quads = render_pass->quad_list;
  EXPECT_EQ(expected_quad_size, quads.size());

  Region layer_remaining(visible_layer_rect);
  for (auto iter = quads.cbegin(); iter != quads.cend(); ++iter) {
    gfx::Rect quad_rect = iter->rect;

    EXPECT_TRUE(visible_layer_rect.Contains(quad_rect)) << iter.index();
    EXPECT_TRUE(layer_remaining.Contains(quad_rect)) << iter.index();
    EXPECT_EQ(iter->needs_blending,
              !iter->shared_quad_state->are_contents_opaque);
    layer_remaining.Subtract(Region(quad_rect));
  }

  // Check if the left-over quad is the same size as the mapped aperture quad in
  // layer space.
  EXPECT_EQ(expected_layer_remaining, layer_remaining.bounds());

  // Verify UV rects
  gfx::Rect bitmap_rect(bitmap_size);
  Region tex_remaining(bitmap_rect);
  for (auto* quad : quads) {
    const viz::TextureDrawQuad* tex_quad =
        viz::TextureDrawQuad::MaterialCast(quad);
    gfx::RectF tex_rect =
        gfx::BoundingRect(tex_quad->uv_top_left, tex_quad->uv_bottom_right);
    tex_rect.Scale(bitmap_size.width(), bitmap_size.height());
    tex_remaining.Subtract(Region(ToRoundedIntRect(tex_rect)));
  }

  EXPECT_EQ(expected_tex_remaining, tex_remaining.bounds());
  Region aperture_region(expected_tex_remaining);
  EXPECT_EQ(aperture_region, tex_remaining);
}

TEST(NinePatchLayerImplTest, VerifyDrawQuads) {
  // Input is a 100x100 bitmap with a 40x50 aperture at x=20, y=30.
  // The bounds of the layer are set to 400x400.
  gfx::Size bitmap_size(100, 100);
  gfx::Size layer_size(400, 500);
  gfx::Rect aperture_rect(20, 30, 40, 50);
  gfx::Rect border(40, 40, 80, 80);
  bool fill_center = false;
  size_t expected_quad_size = 8;
  NinePatchLayerLayoutTest(bitmap_size, aperture_rect, layer_size, border,
                           fill_center, expected_quad_size);

  // The bounds of the layer are set to less than the bitmap size.
  bitmap_size = gfx::Size(100, 100);
  layer_size = gfx::Size(40, 50);
  aperture_rect = gfx::Rect(20, 30, 40, 50);
  border = gfx::Rect(10, 10, 25, 15);
  fill_center = true;
  expected_quad_size = 9;
  NinePatchLayerLayoutTest(bitmap_size, aperture_rect, layer_size, border,
                           fill_center, expected_quad_size);

  // Layer and image sizes are equal.
  bitmap_size = gfx::Size(100, 100);
  layer_size = gfx::Size(100, 100);
  aperture_rect = gfx::Rect(20, 30, 40, 50);
  border = gfx::Rect(20, 30, 40, 50);
  fill_center = true;
  expected_quad_size = 9;
  NinePatchLayerLayoutTest(bitmap_size, aperture_rect, layer_size, border,
                           fill_center, expected_quad_size);
}

TEST(NinePatchLayerImplTest, VerifyDrawQuadsWithOcclusion) {
  // Occlusion removed part of the border and leaves us with 12 patches.
  gfx::Size bitmap_size(100, 100);
  gfx::Rect aperture_rect(30, 30, 40, 40);
  gfx::Size layer_size(400, 400);
  gfx::Rect occlusion(20, 20, 360, 360);
  gfx::Rect border(30, 30, 60, 60);
  size_t expected_quad_size = 12;
  NinePatchLayerLayoutTestWithOcclusion(bitmap_size, aperture_rect, layer_size,
                                        border, occlusion, false,
                                        expected_quad_size);

  bitmap_size = gfx::Size(100, 100);
  aperture_rect = gfx::Rect(20, 30, 60, 40);
  layer_size = gfx::Size(400, 400);
  occlusion = gfx::Rect(10, 10, 380, 380);
  border = gfx::Rect(20, 30, 40, 60);
  expected_quad_size = 12;
  NinePatchLayerLayoutTestWithOcclusion(bitmap_size, aperture_rect, layer_size,
                                        border, occlusion, false,
                                        expected_quad_size);

  // All borders are empty, so nothing should be drawn.
  bitmap_size = gfx::Size(100, 100);
  aperture_rect = gfx::Rect(0, 0, 100, 100);
  layer_size = gfx::Size(400, 400);
  occlusion = gfx::Rect(0, 0, 400, 400);
  border = gfx::Rect(0, 0, 0, 0);
  expected_quad_size = 0;
  NinePatchLayerLayoutTestWithOcclusion(bitmap_size, aperture_rect, layer_size,
                                        border, occlusion, false,
                                        expected_quad_size);

  // Right border is empty, we should have no quads on the right side.
  bitmap_size = gfx::Size(100, 100);
  aperture_rect = gfx::Rect(20, 30, 80, 40);
  layer_size = gfx::Size(400, 400);
  occlusion = gfx::Rect(10, 10, 390, 380);
  border = gfx::Rect(20, 30, 20, 60);
  expected_quad_size = 7;
  NinePatchLayerLayoutTestWithOcclusion(bitmap_size, aperture_rect, layer_size,
                                        border, occlusion, false,
                                        expected_quad_size);
}

TEST(NinePatchLayerImplTest, VerifyDrawQuadsWithEmptyPatches) {
  // The top component of the 9-patch is empty, so there should be no quads for
  // the top three components.
  gfx::Size bitmap_size(100, 100);
  gfx::Size layer_size(100, 100);
  gfx::Rect aperture_rect(10, 0, 80, 90);
  gfx::Rect border(10, 0, 20, 10);
  bool fill_center = false;
  size_t expected_quad_size = 5;
  NinePatchLayerLayoutTest(bitmap_size, aperture_rect, layer_size, border,
                           fill_center, expected_quad_size);

  // The top and left components of the 9-patch are empty, so there should be no
  // quads for the left and top components.
  bitmap_size = gfx::Size(100, 100);
  layer_size = gfx::Size(100, 100);
  aperture_rect = gfx::Rect(0, 0, 90, 90);
  border = gfx::Rect(0, 0, 10, 10);
  fill_center = false;
  expected_quad_size = 3;
  NinePatchLayerLayoutTest(bitmap_size, aperture_rect, layer_size, border,
                           fill_center, expected_quad_size);

  // The aperture is the size of the bitmap and the center doesn't draw.
  bitmap_size = gfx::Size(100, 100);
  layer_size = gfx::Size(100, 100);
  aperture_rect = gfx::Rect(0, 0, 100, 100);
  border = gfx::Rect(0, 0, 0, 0);
  fill_center = false;
  expected_quad_size = 0;
  NinePatchLayerLayoutTest(bitmap_size, aperture_rect, layer_size, border,
                           fill_center, expected_quad_size);

  // The aperture is the size of the bitmap and the center does draw.
  bitmap_size = gfx::Size(100, 100);
  layer_size = gfx::Size(100, 100);
  aperture_rect = gfx::Rect(0, 0, 100, 100);
  border = gfx::Rect(0, 0, 0, 0);
  fill_center = true;
  expected_quad_size = 1;
  NinePatchLayerLayoutTest(bitmap_size, aperture_rect, layer_size, border,
                           fill_center, expected_quad_size);
}

TEST(NinePatchLayerImplTest, Occlusion) {
  gfx::Size layer_size(1000, 1000);
  gfx::Size viewport_size(1000, 1000);

  LayerTestCommon::LayerImplTest impl;

  SkBitmap sk_bitmap;
  sk_bitmap.allocN32Pixels(10, 10);
  sk_bitmap.setImmutable();
  UIResourceId uid = 5;
  UIResourceBitmap bitmap(sk_bitmap);
  impl.host_impl()->CreateUIResource(uid, bitmap);

  NinePatchLayerImpl* nine_patch_layer_impl =
      impl.AddChildToRoot<NinePatchLayerImpl>();
  nine_patch_layer_impl->SetBounds(layer_size);
  nine_patch_layer_impl->SetDrawsContent(true);
  nine_patch_layer_impl->SetUIResourceId(uid);
  nine_patch_layer_impl->SetImageBounds(gfx::Size(10, 10));

  gfx::Rect aperture = gfx::Rect(3, 3, 4, 4);
  gfx::Rect border = gfx::Rect(300, 300, 400, 400);
  nine_patch_layer_impl->SetLayout(aperture, border, gfx::Rect(), true, false);

  impl.CalcDrawProps(viewport_size);

  {
    SCOPED_TRACE("No occlusion");
    gfx::Rect occluded;
    impl.AppendQuadsWithOcclusion(nine_patch_layer_impl, occluded);

    LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(),
                                                 gfx::Rect(layer_size));
    EXPECT_EQ(9u, impl.quad_list().size());
  }

  {
    SCOPED_TRACE("Full occlusion");
    gfx::Rect occluded(nine_patch_layer_impl->visible_layer_rect());
    impl.AppendQuadsWithOcclusion(nine_patch_layer_impl, occluded);

    LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(), gfx::Rect());
    EXPECT_EQ(impl.quad_list().size(), 0u);
  }

  {
    SCOPED_TRACE("Partial occlusion");
    gfx::Rect occluded(0, 0, 500, 1000);
    impl.AppendQuadsWithOcclusion(nine_patch_layer_impl, occluded);

    size_t partially_occluded_count = 0;
    LayerTestCommon::VerifyQuadsAreOccluded(
        impl.quad_list(), occluded, &partially_occluded_count);
    // The layer outputs nine quads, three of which are partially occluded, and
    // three fully occluded.
    EXPECT_EQ(6u, impl.quad_list().size());
    EXPECT_EQ(3u, partially_occluded_count);
  }
}

TEST(NinePatchLayerImplTest, OpaqueRect) {
  gfx::Size layer_size(1000, 1000);
  gfx::Size viewport_size(1000, 1000);

  LayerTestCommon::LayerImplTest impl;

  SkBitmap sk_bitmap_opaque;
  sk_bitmap_opaque.allocN32Pixels(10, 10);
  sk_bitmap_opaque.setImmutable();
  sk_bitmap_opaque.setAlphaType(kOpaque_SkAlphaType);

  UIResourceId uid_opaque = 6;
  UIResourceBitmap bitmap_opaque(sk_bitmap_opaque);
  impl.host_impl()->CreateUIResource(uid_opaque, bitmap_opaque);

  SkBitmap sk_bitmap_alpha;
  sk_bitmap_alpha.allocN32Pixels(10, 10);
  sk_bitmap_alpha.setImmutable();
  sk_bitmap_alpha.setAlphaType(kUnpremul_SkAlphaType);

  UIResourceId uid_alpha = 7;
  UIResourceBitmap bitmap_alpha(sk_bitmap_alpha);

  impl.host_impl()->CreateUIResource(uid_alpha, bitmap_alpha);

  NinePatchLayerImpl *nine_patch_layer_impl =
      impl.AddChildToRoot<NinePatchLayerImpl>();
  nine_patch_layer_impl->SetBounds(layer_size);
  nine_patch_layer_impl->SetDrawsContent(true);

  impl.CalcDrawProps(viewport_size);

  {
    SCOPED_TRACE("Use opaque image");

    nine_patch_layer_impl->SetUIResourceId(uid_opaque);
    nine_patch_layer_impl->SetImageBounds(gfx::Size(10, 10));

    gfx::Rect aperture = gfx::Rect(3, 3, 4, 4);
    gfx::Rect border = gfx::Rect(300, 300, 400, 400);
    nine_patch_layer_impl->SetLayout(aperture, border, gfx::Rect(), true,
                                     false);

    impl.AppendQuadsWithOcclusion(nine_patch_layer_impl, gfx::Rect());

    const auto& quad_list = impl.quad_list();
    for (auto it = quad_list.BackToFrontBegin();
         it != quad_list.BackToFrontEnd(); ++it)
      EXPECT_FALSE(it->ShouldDrawWithBlending());
  }

  {
    SCOPED_TRACE("Use tranparent image");

    nine_patch_layer_impl->SetUIResourceId(uid_alpha);

    impl.AppendQuadsWithOcclusion(nine_patch_layer_impl, gfx::Rect());

    const auto& quad_list = impl.quad_list();
    for (auto it = quad_list.BackToFrontBegin();
         it != quad_list.BackToFrontEnd(); ++it)
      EXPECT_TRUE(it->ShouldDrawWithBlending());
  }
}

}  // namespace
}  // namespace cc
