// 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.

#ifndef FLUTTER_DISPLAY_LIST_DISPLAY_LIST_MATRIX_CLIP_TRACKER_H_
#define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_MATRIX_CLIP_TRACKER_H_

#include <vector>

#include "flutter/display_list/dl_canvas.h"
#include "flutter/fml/logging.h"

#include "third_party/skia/include/core/SkM44.h"
#include "third_party/skia/include/core/SkMatrix.h"
#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkRRect.h"
#include "third_party/skia/include/core/SkRect.h"
#include "third_party/skia/include/core/SkScalar.h"

namespace flutter {

class DisplayListMatrixClipTracker {
 private:
  using ClipOp = DlCanvas::ClipOp;

 public:
  DisplayListMatrixClipTracker(const SkRect& cull_rect, const SkMatrix& matrix);
  DisplayListMatrixClipTracker(const SkRect& cull_rect, const SkM44& matrix);

  // This method should almost never be used as it breaks the encapsulation
  // of the enclosing clips. However it is needed for practical purposes in
  // some rare cases - such as when a saveLayer is collecting rendering
  // operations prior to applying a filter on the entire layer bounds and
  // some of those operations fall outside the enclosing clip, but their
  // filtered content will spread out from where they were rendered on the
  // layer into the enclosing clipped area.
  // Omitting the |cull_rect| argument, or passing nullptr, will restore the
  // cull rect to the initial value it had when the tracker was constructed.
  void resetCullRect(const SkRect* cull_rect = nullptr) {
    current_->resetBounds(cull_rect ? *cull_rect : original_cull_rect_);
  }

  static bool is_3x3(const SkM44& m44);

  SkRect base_device_cull_rect() const { return saved_[0]->device_cull_rect(); }

  bool using_4x4_matrix() const { return current_->is_4x4(); }

  SkM44 matrix_4x4() const { return current_->matrix_4x4(); }
  SkMatrix matrix_3x3() const { return current_->matrix_3x3(); }
  SkRect local_cull_rect() const { return current_->local_cull_rect(); }
  SkRect device_cull_rect() const { return current_->device_cull_rect(); }
  bool content_culled(const SkRect& content_bounds) const {
    return current_->content_culled(content_bounds);
  }
  bool is_cull_rect_empty() const { return current_->is_cull_rect_empty(); }

  void save();
  void restore();
  void reset();
  int getSaveCount() {
    // saved_[0] is always the untouched initial conditions
    // saved_[1] is the first editable stack entry
    return saved_.size() - 1;
  }
  void restoreToCount(int restore_count);

  void translate(SkScalar tx, SkScalar ty) { current_->translate(tx, ty); }
  void scale(SkScalar sx, SkScalar sy) { current_->scale(sx, sy); }
  void skew(SkScalar skx, SkScalar sky) { current_->skew(skx, sky); }
  void rotate(SkScalar degrees) { current_->rotate(degrees); }
  void transform(const SkM44& m44);
  void transform(const SkMatrix& matrix) { current_->transform(matrix); }
  // clang-format off
  void transform2DAffine(
      SkScalar mxx, SkScalar mxy, SkScalar mxt,
      SkScalar myx, SkScalar myy, SkScalar myt);
  void 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);
  // clang-format on
  void setTransform(const SkMatrix& matrix) { current_->setTransform(matrix); }
  void setTransform(const SkM44& m44);
  void setIdentity() { current_->setIdentity(); }
  bool mapRect(SkRect* rect) const { return current_->mapRect(*rect, rect); }

  void clipRect(const SkRect& rect, ClipOp op, bool is_aa) {
    current_->clipBounds(rect, op, is_aa);
  }
  void clipRRect(const SkRRect& rrect, ClipOp op, bool is_aa);
  void clipPath(const SkPath& path, ClipOp op, bool is_aa);

 private:
  class Data {
   public:
    virtual ~Data() = default;

    virtual bool is_4x4() const = 0;

    virtual SkMatrix matrix_3x3() const = 0;
    virtual SkM44 matrix_4x4() const = 0;

    SkRect device_cull_rect() const { return cull_rect_; }
    virtual SkRect local_cull_rect() const = 0;
    virtual bool content_culled(const SkRect& content_bounds) const;
    bool is_cull_rect_empty() const { return cull_rect_.isEmpty(); }

    virtual void translate(SkScalar tx, SkScalar ty) = 0;
    virtual void scale(SkScalar sx, SkScalar sy) = 0;
    virtual void skew(SkScalar skx, SkScalar sky) = 0;
    virtual void rotate(SkScalar degrees) = 0;
    virtual void transform(const SkMatrix& matrix) = 0;
    virtual void transform(const SkM44& m44) = 0;
    virtual void setTransform(const SkMatrix& matrix) = 0;
    virtual void setTransform(const SkM44& m44) = 0;
    virtual void setIdentity() = 0;
    virtual bool mapRect(const SkRect& rect, SkRect* mapped) const = 0;
    virtual bool canBeInverted() const = 0;

    virtual void clipBounds(const SkRect& clip, ClipOp op, bool is_aa);

    virtual void resetBounds(const SkRect& cull_rect);

   protected:
    explicit Data(const SkRect& rect) : cull_rect_(rect) {}

    virtual bool has_perspective() const = 0;

    SkRect cull_rect_;
  };
  friend class Data3x3;
  friend class Data4x4;

  SkRect original_cull_rect_;
  Data* current_;
  std::vector<std::unique_ptr<Data>> saved_;
};

}  // namespace flutter

#endif  // FLUTTER_DISPLAY_LIST_DISPLAY_LIST_MATRIX_CLIP_TRACKER_H_
