// Copyright 2013 The Flutter 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 "flutter/display_list/display_list.h"
#include "flutter/display_list/display_list_builder.h"
#include "flutter/display_list/display_list_complexity.h"
#include "flutter/display_list/display_list_complexity_gl.h"
#include "flutter/display_list/display_list_complexity_metal.h"
#include "flutter/display_list/display_list_sampling_options.h"
#include "flutter/display_list/display_list_test_utils.h"
#include "flutter/testing/testing.h"
#include "third_party/skia/include/core/SkColor.h"

namespace flutter {
namespace testing {

namespace {

std::vector<DisplayListComplexityCalculator*> Calculators() {
  return {DisplayListMetalComplexityCalculator::GetInstance(),
          DisplayListGLComplexityCalculator::GetInstance(),
          DisplayListNaiveComplexityCalculator::GetInstance()};
}

std::vector<DisplayListComplexityCalculator*> AccumulatorCalculators() {
  return {DisplayListMetalComplexityCalculator::GetInstance(),
          DisplayListGLComplexityCalculator::GetInstance()};
}

std::vector<SkPoint> GetTestPoints() {
  std::vector<SkPoint> points;
  points.push_back(SkPoint::Make(0, 0));
  points.push_back(SkPoint::Make(10, 0));
  points.push_back(SkPoint::Make(10, 10));
  points.push_back(SkPoint::Make(20, 10));
  points.push_back(SkPoint::Make(20, 20));

  return points;
}

}  // namespace

TEST(DisplayListComplexity, EmptyDisplayList) {
  auto display_list = GetSampleDisplayList(0);

  auto calculators = Calculators();
  for (auto calculator : calculators) {
    ASSERT_EQ(calculator->Compute(display_list.get()), 0u);
  }
}

TEST(DisplayListComplexity, DisplayListCeiling) {
  auto display_list = GetSampleDisplayList();

  auto calculators = AccumulatorCalculators();
  for (auto calculator : calculators) {
    calculator->SetComplexityCeiling(10u);
    ASSERT_EQ(calculator->Compute(display_list.get()), 10u);
    calculator->SetComplexityCeiling(std::numeric_limits<unsigned int>::max());
  }
}

TEST(DisplayListComplexity, NestedDisplayList) {
  auto display_list = GetSampleNestedDisplayList();

  auto calculators = Calculators();
  for (auto calculator : calculators) {
    // There's only one draw call in the "outer" DisplayList, which calls
    // drawDisplayList with the "inner" DisplayList. To ensure we are
    // recursing correctly into the inner DisplayList, check that we aren't
    // returning 0 (if the function is a no-op) or 1 (as the op_count is 1)
    ASSERT_GT(calculator->Compute(display_list.get()), 1u);
  }
}

TEST(DisplayListComplexity, AntiAliasing) {
  DisplayListBuilder builder_no_aa;
  builder_no_aa.drawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100));
  auto display_list_no_aa = builder_no_aa.Build();

  DisplayListBuilder builder_aa;
  builder_aa.setAntiAlias(true);
  builder_aa.drawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100));
  auto display_list_aa = builder_aa.Build();

  auto calculators = AccumulatorCalculators();
  for (auto calculator : calculators) {
    ASSERT_NE(calculator->Compute(display_list_no_aa.get()),
              calculator->Compute(display_list_aa.get()));
  }
}

TEST(DisplayListComplexity, StrokeWidth) {
  DisplayListBuilder builder_stroke_0;
  builder_stroke_0.setStrokeWidth(0.0f);
  builder_stroke_0.drawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100));
  auto display_list_stroke_0 = builder_stroke_0.Build();

  DisplayListBuilder builder_stroke_1;
  builder_stroke_1.setStrokeWidth(1.0f);
  builder_stroke_1.drawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100));
  auto display_list_stroke_1 = builder_stroke_1.Build();

  auto calculators = AccumulatorCalculators();
  for (auto calculator : calculators) {
    ASSERT_NE(calculator->Compute(display_list_stroke_0.get()),
              calculator->Compute(display_list_stroke_1.get()));
  }
}

TEST(DisplayListComplexity, Style) {
  DisplayListBuilder builder_filled;
  builder_filled.setStyle(DlDrawStyle::kFill);
  builder_filled.drawRect(SkRect::MakeXYWH(10, 10, 80, 80));
  auto display_list_filled = builder_filled.Build();

  DisplayListBuilder builder_stroked;
  builder_stroked.setStyle(DlDrawStyle::kStroke);
  builder_stroked.drawRect(SkRect::MakeXYWH(10, 10, 80, 80));
  auto display_list_stroked = builder_stroked.Build();

  auto calculators = AccumulatorCalculators();
  for (auto calculator : calculators) {
    ASSERT_NE(calculator->Compute(display_list_filled.get()),
              calculator->Compute(display_list_stroked.get()));
  }
}

TEST(DisplayListComplexity, SaveLayers) {
  DisplayListBuilder builder;
  builder.saveLayer(nullptr, true);
  auto display_list = builder.Build();

  auto calculators = AccumulatorCalculators();
  for (auto calculator : calculators) {
    ASSERT_NE(calculator->Compute(display_list.get()), 0u);
  }
}

TEST(DisplayListComplexity, DrawPath) {
  DisplayListBuilder builder_line;
  SkPath linePath;
  linePath.moveTo(SkPoint::Make(0, 0));
  linePath.lineTo(SkPoint::Make(10, 10));
  linePath.close();
  builder_line.drawPath(linePath);
  auto display_list_line = builder_line.Build();

  DisplayListBuilder builder_quad;
  SkPath quadPath;
  quadPath.moveTo(SkPoint::Make(0, 0));
  quadPath.quadTo(SkPoint::Make(10, 10), SkPoint::Make(10, 20));
  quadPath.close();
  builder_quad.drawPath(quadPath);
  auto display_list_quad = builder_quad.Build();

  DisplayListBuilder builder_conic;
  SkPath conicPath;
  conicPath.moveTo(SkPoint::Make(0, 0));
  conicPath.conicTo(SkPoint::Make(10, 10), SkPoint::Make(10, 20), 1.5f);
  conicPath.close();
  builder_conic.drawPath(conicPath);
  auto display_list_conic = builder_conic.Build();

  DisplayListBuilder builder_cubic;
  SkPath cubicPath;
  cubicPath.moveTo(SkPoint::Make(0, 0));
  cubicPath.cubicTo(SkPoint::Make(10, 10), SkPoint::Make(10, 20),
                    SkPoint::Make(20, 20));
  builder_cubic.drawPath(cubicPath);
  auto display_list_cubic = builder_cubic.Build();

  auto calculators = AccumulatorCalculators();
  for (auto calculator : calculators) {
    ASSERT_NE(calculator->Compute(display_list_line.get()), 0u);
    ASSERT_NE(calculator->Compute(display_list_quad.get()), 0u);
    ASSERT_NE(calculator->Compute(display_list_conic.get()), 0u);
    ASSERT_NE(calculator->Compute(display_list_cubic.get()), 0u);
  }
}

TEST(DisplayListComplexity, DrawShadow) {
  DisplayListBuilder builder_line;
  SkPath linePath;
  linePath.moveTo(SkPoint::Make(0, 0));
  linePath.lineTo(SkPoint::Make(10, 10));
  linePath.close();
  builder_line.drawShadow(linePath, SK_ColorRED, 10.0f, false, 1.0f);
  auto display_list_line = builder_line.Build();

  DisplayListBuilder builder_quad;
  SkPath quadPath;
  quadPath.moveTo(SkPoint::Make(0, 0));
  quadPath.quadTo(SkPoint::Make(10, 10), SkPoint::Make(10, 20));
  quadPath.close();
  builder_quad.drawShadow(quadPath, SK_ColorRED, 10.0f, false, 1.0f);
  auto display_list_quad = builder_quad.Build();

  DisplayListBuilder builder_conic;
  SkPath conicPath;
  conicPath.moveTo(SkPoint::Make(0, 0));
  conicPath.conicTo(SkPoint::Make(10, 10), SkPoint::Make(10, 20), 1.5f);
  conicPath.close();
  builder_conic.drawShadow(conicPath, SK_ColorRED, 10.0f, false, 1.0f);
  auto display_list_conic = builder_conic.Build();

  DisplayListBuilder builder_cubic;
  SkPath cubicPath;
  cubicPath.moveTo(SkPoint::Make(0, 0));
  cubicPath.cubicTo(SkPoint::Make(10, 10), SkPoint::Make(10, 20),
                    SkPoint::Make(20, 20));
  builder_cubic.drawShadow(cubicPath, SK_ColorRED, 10.0f, false, 1.0f);
  auto display_list_cubic = builder_cubic.Build();

  auto calculators = AccumulatorCalculators();
  for (auto calculator : calculators) {
    ASSERT_NE(calculator->Compute(display_list_line.get()), 0u);
    ASSERT_NE(calculator->Compute(display_list_quad.get()), 0u);
    ASSERT_NE(calculator->Compute(display_list_conic.get()), 0u);
    ASSERT_NE(calculator->Compute(display_list_cubic.get()), 0u);
  }
}

TEST(DisplayListComplexity, DrawOval) {
  DisplayListBuilder builder;
  builder.drawOval(SkRect::MakeXYWH(10, 10, 100, 80));
  auto display_list = builder.Build();

  auto calculators = AccumulatorCalculators();
  for (auto calculator : calculators) {
    ASSERT_NE(calculator->Compute(display_list.get()), 0u);
  }
}

TEST(DisplayListComplexity, DrawCircle) {
  DisplayListBuilder builder;
  builder.drawCircle(SkPoint::Make(50, 50), 10.0f);
  auto display_list = builder.Build();

  auto calculators = AccumulatorCalculators();
  for (auto calculator : calculators) {
    ASSERT_NE(calculator->Compute(display_list.get()), 0u);
  }
}

TEST(DisplayListComplexity, DrawRRect) {
  DisplayListBuilder builder;
  builder.drawRRect(
      SkRRect::MakeRectXY(SkRect::MakeXYWH(10, 10, 80, 80), 2.0f, 3.0f));
  auto display_list = builder.Build();

  auto calculators = AccumulatorCalculators();
  for (auto calculator : calculators) {
    ASSERT_NE(calculator->Compute(display_list.get()), 0u);
  }
}

TEST(DisplayListComplexity, DrawDRRect) {
  DisplayListBuilder builder;
  SkRRect outer =
      SkRRect::MakeRectXY(SkRect::MakeXYWH(10, 10, 80, 80), 2.0f, 3.0f);
  SkRRect inner =
      SkRRect::MakeRectXY(SkRect::MakeXYWH(15, 15, 70, 70), 1.5f, 1.5f);
  builder.drawDRRect(outer, inner);
  auto display_list = builder.Build();

  auto calculators = AccumulatorCalculators();
  for (auto calculator : calculators) {
    ASSERT_NE(calculator->Compute(display_list.get()), 0u);
  }
}

TEST(DisplayListComplexity, DrawArc) {
  DisplayListBuilder builder;
  builder.drawArc(SkRect::MakeXYWH(10, 10, 100, 80), 0.0f, 10.0f, true);
  auto display_list = builder.Build();

  auto calculators = AccumulatorCalculators();
  for (auto calculator : calculators) {
    ASSERT_NE(calculator->Compute(display_list.get()), 0u);
  }
}

TEST(DisplayListComplexity, DrawVertices) {
  auto points = GetTestPoints();
  auto vertices = DlVertices::Make(DlVertexMode::kTriangles, points.size(),
                                   points.data(), nullptr, nullptr);
  DisplayListBuilder builder;
  builder.drawVertices(vertices, DlBlendMode::kSrc);
  auto display_list = builder.Build();

  auto calculators = AccumulatorCalculators();
  for (auto calculator : calculators) {
    ASSERT_NE(calculator->Compute(display_list.get()), 0u);
  }
}

TEST(DisplayListComplexity, DrawTextBlob) {
  auto text_blob = SkTextBlob::MakeFromString(
      "The quick brown fox jumps over the lazy dog.", SkFont());

  DisplayListBuilder builder;
  builder.drawTextBlob(text_blob, 0.0f, 0.0f);
  auto display_list = builder.Build();

  DisplayListBuilder builder_multiple;
  builder_multiple.drawTextBlob(text_blob, 0.0f, 0.0f);
  builder_multiple.drawTextBlob(text_blob, 0.0f, 0.0f);
  auto display_list_multiple = builder_multiple.Build();

  auto calculators = AccumulatorCalculators();
  for (auto calculator : calculators) {
    ASSERT_NE(calculator->Compute(display_list.get()), 0u);
    ASSERT_GT(calculator->Compute(display_list_multiple.get()),
              calculator->Compute(display_list.get()));
  }
}

TEST(DisplayListComplexity, DrawPoints) {
  auto points = GetTestPoints();
  DisplayListBuilder builder_lines;
  builder_lines.drawPoints(SkCanvas::kLines_PointMode, points.size(),
                           points.data());
  auto display_list_lines = builder_lines.Build();

  DisplayListBuilder builder_points;
  builder_points.drawPoints(SkCanvas::kPoints_PointMode, points.size(),
                            points.data());
  auto display_list_points = builder_points.Build();

  DisplayListBuilder builder_polygon;
  builder_polygon.drawPoints(SkCanvas::kPolygon_PointMode, points.size(),
                             points.data());
  auto display_list_polygon = builder_polygon.Build();

  auto calculators = AccumulatorCalculators();
  for (auto calculator : calculators) {
    ASSERT_NE(calculator->Compute(display_list_lines.get()), 0u);
    ASSERT_NE(calculator->Compute(display_list_points.get()), 0u);
    ASSERT_NE(calculator->Compute(display_list_polygon.get()), 0u);
  }
}

TEST(DisplayListComplexity, DrawImage) {
  SkImageInfo info =
      SkImageInfo::Make(50, 50, SkColorType::kRGBA_8888_SkColorType,
                        SkAlphaType::kPremul_SkAlphaType);
  SkBitmap bitmap;
  bitmap.allocPixels(info, 0);
  auto image = SkImage::MakeFromBitmap(bitmap);

  DisplayListBuilder builder;
  builder.drawImage(DlImage::Make(image), SkPoint::Make(0, 0),
                    DlImageSampling::kNearestNeighbor, false);
  auto display_list = builder.Build();

  auto calculators = AccumulatorCalculators();
  for (auto calculator : calculators) {
    ASSERT_NE(calculator->Compute(display_list.get()), 0u);
  }
}

TEST(DisplayListComplexity, DrawImageNine) {
  SkImageInfo info =
      SkImageInfo::Make(50, 50, SkColorType::kRGBA_8888_SkColorType,
                        SkAlphaType::kPremul_SkAlphaType);
  SkBitmap bitmap;
  bitmap.allocPixels(info, 0);
  auto image = SkImage::MakeFromBitmap(bitmap);

  SkIRect center = SkIRect::MakeXYWH(5, 5, 20, 20);
  SkRect dest = SkRect::MakeXYWH(0, 0, 50, 50);

  DisplayListBuilder builder;
  builder.drawImageNine(DlImage::Make(image), center, dest,
                        DlFilterMode::kNearest, true);
  auto display_list = builder.Build();

  auto calculators = AccumulatorCalculators();
  for (auto calculator : calculators) {
    ASSERT_NE(calculator->Compute(display_list.get()), 0u);
  }
}

TEST(DisplayListComplexity, DrawImageRect) {
  SkImageInfo info =
      SkImageInfo::Make(50, 50, SkColorType::kRGBA_8888_SkColorType,
                        SkAlphaType::kPremul_SkAlphaType);
  SkBitmap bitmap;
  bitmap.allocPixels(info, 0);
  auto image = SkImage::MakeFromBitmap(bitmap);

  SkRect src = SkRect::MakeXYWH(0, 0, 50, 50);
  SkRect dest = SkRect::MakeXYWH(0, 0, 50, 50);

  DisplayListBuilder builder;
  builder.drawImageRect(DlImage::Make(image), src, dest,
                        DlImageSampling::kNearestNeighbor, true);
  auto display_list = builder.Build();

  auto calculators = AccumulatorCalculators();
  for (auto calculator : calculators) {
    ASSERT_NE(calculator->Compute(display_list.get()), 0u);
  }
}

TEST(DisplayListComplexity, DrawAtlas) {
  SkImageInfo info =
      SkImageInfo::Make(50, 50, SkColorType::kRGBA_8888_SkColorType,
                        SkAlphaType::kPremul_SkAlphaType);
  SkBitmap bitmap;
  bitmap.allocPixels(info, 0);
  auto image = SkImage::MakeFromBitmap(bitmap);

  std::vector<SkRect> rects;
  std::vector<SkRSXform> xforms;
  for (int i = 0; i < 10; i++) {
    rects.push_back(SkRect::MakeXYWH(0, 0, 10, 10));
    xforms.push_back(SkRSXform::Make(0, 0, 0, 0));
  }

  DisplayListBuilder builder;
  builder.drawAtlas(DlImage::Make(image), xforms.data(), rects.data(), nullptr,
                    10, DlBlendMode::kSrc, DlImageSampling::kNearestNeighbor,
                    nullptr, true);
  auto display_list = builder.Build();

  auto calculators = AccumulatorCalculators();
  for (auto calculator : calculators) {
    ASSERT_NE(calculator->Compute(display_list.get()), 0u);
  }
}

}  // namespace testing
}  // namespace flutter
