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

#include "flutter/display_list/dl_builder.h"
#include "flutter/fml/logging.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_;
};

bool DisplayListMatrixClipTracker::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)
    : original_cull_rect_(cull_rect) {
  // 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();
  save();  // saved_[0] will always be the initial settings
}

DisplayListMatrixClipTracker::DisplayListMatrixClipTracker(
    const SkRect& cull_rect,
    const SkM44& m44)
    : original_cull_rect_(cull_rect) {
  // 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();
  save();  // saved_[0] will always be the initial settings
}

// 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() {
  if (saved_.size() > 2) {
    saved_.pop_back();
    current_ = saved_.back().get();
  }
}

void DisplayListMatrixClipTracker::reset() {
  while (saved_.size() > 1) {
    saved_.pop_back();
    current_ = saved_.back().get();
  }
  save();  // saved_[0] will always be the initial settings
}

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);
}

bool DisplayListMatrixClipTracker::inverseTransform(
    const DisplayListMatrixClipTracker& tracker_) {
  if (tracker_.using_4x4_matrix()) {
    SkM44 inverse;
    if (tracker_.matrix_4x4().invert(&inverse)) {
      transform(inverse);
      return true;
    }
  } else {
    SkMatrix inverse;
    if (tracker_.matrix_3x3().invert(&inverse)) {
      transform(inverse);
      return true;
    }
  }
  return false;
}

void DisplayListMatrixClipTracker::clipRRect(const SkRRect& rrect,
                                             ClipOp op,
                                             bool is_aa) {
  switch (op) {
    case ClipOp::kIntersect:
      break;
    case ClipOp::kDifference:
      if (!rrect.isRect()) {
        return;
      }
      break;
  }
  current_->clipBounds(rrect.getBounds(), op, is_aa);
}
void DisplayListMatrixClipTracker::clipPath(const SkPath& path,
                                            ClipOp 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 ClipOp::kIntersect:
        op = ClipOp::kDifference;
        break;
      case ClipOp::kDifference:
        op = ClipOp::kIntersect;
        break;
    }
  }

  SkRect bounds;
  switch (op) {
    case ClipOp::kIntersect:
      bounds = path.getBounds();
      break;
    case ClipOp::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::resetBounds(const SkRect& cull_rect) {
  if (!cull_rect.isEmpty()) {
    SkRect rect;
    mapRect(cull_rect, &rect);
    if (!rect.isEmpty()) {
      cull_rect_ = rect;
      return;
    }
  }
  cull_rect_.setEmpty();
}

void DisplayListMatrixClipTracker::Data::clipBounds(const SkRect& clip,
                                                    ClipOp 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 ClipOp::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 ClipOp::kDifference: {
      if (clip.isEmpty()) {
        break;
      }
      SkRect rect;
      if (mapRect(clip, &rect)) {
        // This technique only works if the transform is rect -> rect
        if (is_aa) {
          SkIRect rounded;
          rect.round(&rounded);
          if (rounded.isEmpty()) {
            break;
          }
          rect.set(rounded);
        }
        if (!rect.intersects(cull_rect_)) {
          break;
        }
        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 = cull_rect_.fTop;
          SkScalar btm = cull_rect_.fBottom;
          if (rect.fTop <= top) {
            top = rect.fBottom;
          }
          if (rect.fBottom >= btm) {
            btm = rect.fTop;
          }
          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 = cull_rect_.fLeft;
          SkScalar rgt = cull_rect_.fRight;
          if (rect.fLeft <= lft) {
            lft = rect.fRight;
          }
          if (rect.fRight >= rgt) {
            rgt = rect.fLeft;
          }
          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
