// 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_matrix_clip_tracker.h"

#include "flutter/display_list/display_list_builder.h"
#include "flutter/fml/logging.h"
#include "third_party/skia/include/core/SkPath.h"

namespace flutter {

class Data4x4 : public DisplayListMatrixClipTracker::Data {
 public:
  Data4x4(const SkM44& m44, const SkRect& rect) : Data(rect), m44_(m44) {}
  explicit Data4x4(const Data* copy)
      : Data(copy->device_cull_rect()), m44_(copy->matrix_4x4()) {}

  ~Data4x4() override = default;

  bool is_4x4() const override { return true; }

  SkMatrix matrix_3x3() const override { return m44_.asM33(); }
  SkM44 matrix_4x4() const override { return m44_; }
  SkRect local_cull_rect() const override;

  void translate(SkScalar tx, SkScalar ty) override {
    m44_.preTranslate(tx, ty);
  }
  void scale(SkScalar sx, SkScalar sy) override { m44_.preScale(sx, sy); }
  void skew(SkScalar skx, SkScalar sky) override {
    m44_.preConcat(SkMatrix::Skew(skx, sky));
  }
  void rotate(SkScalar degrees) override {
    m44_.preConcat(SkMatrix::RotateDeg(degrees));
  }
  void transform(const SkMatrix& matrix) override { m44_.preConcat(matrix); }
  void transform(const SkM44& m44) override { m44_.preConcat(m44); }
  void setTransform(const SkMatrix& matrix) override { m44_ = SkM44(matrix); }
  void setTransform(const SkM44& m44) override { m44_ = m44; }
  void setIdentity() override { m44_.setIdentity(); }
  bool mapRect(const SkRect& rect, SkRect* mapped) const override {
    return m44_.asM33().mapRect(mapped, rect);
  }
  bool canBeInverted() const override { return m44_.asM33().invert(nullptr); }

 protected:
  bool has_perspective() const override;

 private:
  SkM44 m44_;
};

class Data3x3 : public DisplayListMatrixClipTracker::Data {
 public:
  Data3x3(const SkMatrix& matrix, const SkRect& rect)
      : Data(rect), matrix_(matrix) {}
  explicit Data3x3(const Data* copy)
      : Data(copy->device_cull_rect()), matrix_(copy->matrix_3x3()) {}

  ~Data3x3() override = default;

  bool is_4x4() const override { return false; }

  SkMatrix matrix_3x3() const override { return matrix_; }
  SkM44 matrix_4x4() const override { return SkM44(matrix_); }
  SkRect local_cull_rect() const override;

  void translate(SkScalar tx, SkScalar ty) override {
    matrix_.preTranslate(tx, ty);
  }
  void scale(SkScalar sx, SkScalar sy) override { matrix_.preScale(sx, sy); }
  void skew(SkScalar skx, SkScalar sky) override { matrix_.preSkew(skx, sky); }
  void rotate(SkScalar degrees) override { matrix_.preRotate(degrees); }
  void transform(const SkMatrix& matrix) override { matrix_.preConcat(matrix); }
  void transform(const SkM44& m44) override {
    FML_CHECK(false) << "SkM44 was concatenated without upgrading Data";
  }
  void setTransform(const SkMatrix& matrix) override { matrix_ = matrix; }
  void setTransform(const SkM44& m44) override {
    FML_CHECK(false) << "SkM44 was set without upgrading Data";
  }
  void setIdentity() override { matrix_.setIdentity(); }
  bool mapRect(const SkRect& rect, SkRect* mapped) const override {
    return matrix_.mapRect(mapped, rect);
  }
  bool canBeInverted() const override { return matrix_.invert(nullptr); }

 protected:
  bool has_perspective() const override { return matrix_.hasPerspective(); }

 private:
  SkMatrix matrix_;
};

static bool is_3x3(const SkM44& m) {
  // clang-format off
  return (                                      m.rc(0, 2) == 0 &&
                                                m.rc(1, 2) == 0 &&
          m.rc(2, 0) == 0 && m.rc(2, 1) == 0 && m.rc(2, 2) == 1 && m.rc(2, 3) == 0 &&
                                                m.rc(3, 2) == 0);
  // clang-format on
}

DisplayListMatrixClipTracker::DisplayListMatrixClipTracker(
    const SkRect& cull_rect,
    const SkMatrix& matrix) {
  // isEmpty protects us against NaN as we normalize any empty cull rects
  SkRect cull = cull_rect.isEmpty() ? SkRect::MakeEmpty() : cull_rect;
  saved_.emplace_back(std::make_unique<Data3x3>(matrix, cull));
  current_ = saved_.back().get();
}

DisplayListMatrixClipTracker::DisplayListMatrixClipTracker(
    const SkRect& cull_rect,
    const SkM44& m44) {
  // isEmpty protects us against NaN as we normalize any empty cull rects
  SkRect cull = cull_rect.isEmpty() ? SkRect::MakeEmpty() : cull_rect;
  if (is_3x3(m44)) {
    saved_.emplace_back(std::make_unique<Data3x3>(m44.asM33(), cull));
  } else {
    saved_.emplace_back(std::make_unique<Data4x4>(m44, cull));
  }
  current_ = saved_.back().get();
}

// clang-format off
void DisplayListMatrixClipTracker::transform2DAffine(
    SkScalar mxx, SkScalar mxy, SkScalar mxt,
    SkScalar myx, SkScalar myy, SkScalar myt) {
  if (!current_->is_4x4()) {
    transform(SkMatrix::MakeAll(mxx, mxy, mxt,
                                myx, myy, myt,
                                0,   0,   1));
  } else {
    transform(SkM44(mxx, mxy, 0, mxt,
                    myx, myy, 0, myt,
                    0,   0,   1, 0,
                    0,   0,   0, 1));
  }
}
void DisplayListMatrixClipTracker::transformFullPerspective(
    SkScalar mxx, SkScalar mxy, SkScalar mxz, SkScalar mxt,
    SkScalar myx, SkScalar myy, SkScalar myz, SkScalar myt,
    SkScalar mzx, SkScalar mzy, SkScalar mzz, SkScalar mzt,
    SkScalar mwx, SkScalar mwy, SkScalar mwz, SkScalar mwt) {
  if (!current_->is_4x4()) {
    if (                        mxz == 0 &&
                                myz == 0 &&
        mzx == 0 && mzy == 0 && mzz == 1 && mzt == 0 &&
                                mwz == 0) {
        transform(SkMatrix::MakeAll(mxx, mxy, mxt,
                                    myx, myy, myt,
                                    mwx, mwy, mwt));
        return;
    }
  }

  transform(SkM44(mxx, mxy, mxz, mxt,
                  myx, myy, myz, myt,
                  mzx, mzy, mzz, mzt,
                  mwx, mwy, mwz, mwt));
}
// clang-format on

void DisplayListMatrixClipTracker::save() {
  if (current_->is_4x4()) {
    saved_.emplace_back(std::make_unique<Data4x4>(current_));
  } else {
    saved_.emplace_back(std::make_unique<Data3x3>(current_));
  }
  current_ = saved_.back().get();
}

void DisplayListMatrixClipTracker::restore() {
  saved_.pop_back();
  current_ = saved_.back().get();
}

void DisplayListMatrixClipTracker::restoreToCount(int restore_count) {
  FML_DCHECK(restore_count <= getSaveCount());
  if (restore_count < 1) {
    restore_count = 1;
  }
  while (restore_count < getSaveCount()) {
    restore();
  }
}

void DisplayListMatrixClipTracker::transform(const SkM44& m44) {
  if (!current_->is_4x4()) {
    if (is_3x3(m44)) {
      current_->transform(m44.asM33());
      return;
    }
    saved_.back() = std::make_unique<Data4x4>(current_);
    current_ = saved_.back().get();
  }
  current_->transform(m44);
}

void DisplayListMatrixClipTracker::setTransform(const SkM44& m44) {
  if (!current_->is_4x4()) {
    if (is_3x3(m44)) {
      current_->setTransform(m44.asM33());
      return;
    }
    saved_.back() = std::make_unique<Data4x4>(current_);
    current_ = saved_.back().get();
  }
  current_->setTransform(m44);
}

void DisplayListMatrixClipTracker::clipRRect(const SkRRect& rrect,
                                             SkClipOp op,
                                             bool is_aa) {
  switch (op) {
    case SkClipOp::kIntersect:
      break;
    case SkClipOp::kDifference:
      if (!rrect.isRect()) {
        return;
      }
      break;
  }
  current_->clipBounds(rrect.getBounds(), op, is_aa);
}
void DisplayListMatrixClipTracker::clipPath(const SkPath& path,
                                            SkClipOp op,
                                            bool is_aa) {
  // Map "kDifference of inverse path" to "kIntersect of the original path" and
  // map "kIntersect of inverse path" to "kDifference of the original path"
  if (path.isInverseFillType()) {
    switch (op) {
      case SkClipOp::kIntersect:
        op = SkClipOp::kDifference;
        break;
      case SkClipOp::kDifference:
        op = SkClipOp::kIntersect;
        break;
    }
  }

  SkRect bounds;
  switch (op) {
    case SkClipOp::kIntersect:
      bounds = path.getBounds();
      break;
    case SkClipOp::kDifference:
      if (!path.isRect(&bounds)) {
        return;
      }
      break;
  }
  current_->clipBounds(bounds, op, is_aa);
}

bool DisplayListMatrixClipTracker::Data::content_culled(
    const SkRect& content_bounds) const {
  if (cull_rect_.isEmpty() || content_bounds.isEmpty()) {
    return true;
  }
  if (!canBeInverted()) {
    return true;
  }
  if (has_perspective()) {
    return false;
  }
  SkRect mapped;
  mapRect(content_bounds, &mapped);
  return !mapped.intersects(cull_rect_);
}

void DisplayListMatrixClipTracker::Data::clipBounds(const SkRect& clip,
                                                    SkClipOp op,
                                                    bool is_aa) {
  if (cull_rect_.isEmpty()) {
    // No point in intersecting further.
    return;
  }
  if (has_perspective()) {
    // We can conservatively ignore this clip.
    return;
  }
  switch (op) {
    case SkClipOp::kIntersect: {
      if (clip.isEmpty()) {
        cull_rect_.setEmpty();
        break;
      }
      SkRect rect;
      mapRect(clip, &rect);
      if (is_aa) {
        rect.roundOut(&rect);
      }
      if (!cull_rect_.intersect(rect)) {
        cull_rect_.setEmpty();
      }
      break;
    }
    case SkClipOp::kDifference: {
      if (clip.isEmpty() || !clip.intersects(cull_rect_)) {
        break;
      }
      SkRect rect;
      if (mapRect(clip, &rect)) {
        // This technique only works if it is rect -> rect
        if (is_aa) {
          SkIRect rounded;
          rect.round(&rounded);
          if (rounded.isEmpty()) {
            break;
          }
          rect.set(rounded);
        }
        if (rect.fLeft <= cull_rect_.fLeft &&
            rect.fRight >= cull_rect_.fRight) {
          // bounds spans entire width of cull_rect_
          // therefore we can slice off a top or bottom
          // edge of the cull_rect_.
          SkScalar top = std::max(rect.fBottom, cull_rect_.fTop);
          SkScalar btm = std::min(rect.fTop, cull_rect_.fBottom);
          if (top < btm) {
            cull_rect_.fTop = top;
            cull_rect_.fBottom = btm;
          } else {
            cull_rect_.setEmpty();
          }
        } else if (rect.fTop <= cull_rect_.fTop &&
                   rect.fBottom >= cull_rect_.fBottom) {
          // bounds spans entire height of cull_rect_
          // therefore we can slice off a left or right
          // edge of the cull_rect_.
          SkScalar lft = std::max(rect.fRight, cull_rect_.fLeft);
          SkScalar rgt = std::min(rect.fLeft, cull_rect_.fRight);
          if (lft < rgt) {
            cull_rect_.fLeft = lft;
            cull_rect_.fRight = rgt;
          } else {
            cull_rect_.setEmpty();
          }
        }
      }
      break;
    }
  }
}

SkRect Data4x4::local_cull_rect() const {
  if (cull_rect_.isEmpty()) {
    return cull_rect_;
  }
  SkMatrix inverse;
  if (!m44_.asM33().invert(&inverse)) {
    return SkRect::MakeEmpty();
  }
  if (has_perspective()) {
    // We could do a 4-point long-form conversion, but since this is
    // only used for culling, let's just return a non-constricting
    // cull rect.
    return DisplayListBuilder::kMaxCullRect;
  }
  return inverse.mapRect(cull_rect_);
}

bool Data4x4::has_perspective() const {
  return (m44_.rc(3, 0) != 0 ||  //
          m44_.rc(3, 1) != 0 ||  //
          m44_.rc(3, 2) != 0 ||  //
          m44_.rc(3, 3) != 1);
}

SkRect Data3x3::local_cull_rect() const {
  if (cull_rect_.isEmpty()) {
    return cull_rect_;
  }
  SkMatrix inverse;
  if (!matrix_.invert(&inverse)) {
    return SkRect::MakeEmpty();
  }
  if (matrix_.hasPerspective()) {
    // We could do a 4-point long-form conversion, but since this is
    // only used for culling, let's just return a non-constricting
    // cull rect.
    return DisplayListBuilder::kMaxCullRect;
  }
  return inverse.mapRect(cull_rect_);
}

}  // namespace flutter
