// 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_FLOW_LAYERS_LAYER_STATE_STACK_H_
#define FLUTTER_FLOW_LAYERS_LAYER_STATE_STACK_H_

#include "flutter/display_list/dl_canvas.h"
#include "flutter/flow/embedded_views.h"
#include "flutter/flow/paint_utils.h"

namespace flutter {

/// The LayerStateStack manages the inherited state passed down between
/// |Layer| objects in a |LayerTree| during |Preroll| and |Paint|.
///
/// More specifically, it manages the clip and transform state during
/// recursive rendering and will hold and lazily apply opacity, ImageFilter
/// and ColorFilter attributes to recursive content. This is not a truly
/// general state management mechnanism as it makes assumptions that code
/// will be applying the attributes to rendered content that happens in
/// recursive calls. The automatic save/restore mechanisms only work in
/// a context where C++ auto-destruct calls will engage the restore at
/// the end of a code block and that any applied attributes will only
/// be applied to the content rendered inside that block. These restrictions
/// match the organization of the |LayerTree| methods precisely.
///
/// The stack can manage a single state delegate. The delegate will provide
/// tracking of the current transform and clip and will also execute
/// saveLayer calls at the appropriate time if it is a rendering delegate.
/// The delegate can be swapped out on the fly (as is typically done by
/// PlatformViewLayer when recording the state for multiple "overlay"
/// layers that occur between embedded view subtrees. The old delegate
/// will be restored to its original state before it became a delegate
/// and the new delegate will have all of the state recorded by the stack
/// replayed into it to bring it up to speed with the current rendering
/// context.
///
/// The delegate can be any one of:
///   - Preroll delegate: used during Preroll to remember the outstanding
///                       state for embedded platform layers
///   - DlCanvas: used during Paint for rendering output
/// The stack will know which state needs to be conveyed to any of these
/// delegates and when is the best time to convey that state (i.e. lazy
/// saveLayer calls for example).
///
/// The rendering state attributes will be automatically applied to the
/// nested content using a |saveLayer| call at the point at which we
/// encounter rendered content (i.e. various nested layers that exist only
/// to apply new state will not trigger the |saveLayer| and the attributes
/// can accumulate until we reach actual content that is rendered.) Some
/// rendered content can avoid the |saveLayer| if it reports to the object
/// that it is able to apply all of the attributes that happen to be
/// outstanding (accumulated from parent state-modifiers). A |ContainerLayer|
/// can also monitor the attribute rendering capabilities of a list of
/// children and can ask the object to apply a protective |saveLayer| or
/// not based on the negotiated capabilities of the entire group.
///
/// Any code that is planning to modify the clip, transform, or rendering
/// attributes for its child content must start by calling the |save| method
/// which returns a MutatorContext object. The methods that modify such
/// state only exist on the MutatorContext object so it is difficult to get
/// that wrong, but the caller must make sure that the call happens within
/// a C++ code block that will define the "rendering scope" of those
/// state changes as they will be automatically restored on exit from that
/// block. Note that the layer might make similar state calls directly on
/// the canvas or builder during the Paint cycle (via saveLayer, transform,
/// or clip calls), but should avoid doing so if there is any nested content
/// that needs to track or react to those state calls.
///
/// Code that needs to render content can simply inform the parent of their
/// abilities by setting the |PrerollContext::renderable_state_flags| during
/// |Preroll| and then render with those attributes during |Paint| by
/// requesting the outstanding values of those attributes from the state_stack
/// object. Individual leaf layers can ignore this feature as the default
/// behavior during |Preroll| will have their parent |ContainerLayer| assume
/// that they cannot render any outstanding state attributes and will apply
/// the protective saveLayer on their behalf if needed. As such, this object
/// only provides "opt-in" features for leaf layers and no responsibilities
/// otherwise.
/// See |LayerStateStack::fill|
/// See |LayerStateStack::outstanding_opacity|
/// See |LayerStateStack::outstanding_color_filter|
/// See |LayerStateStack::outstanding_image_filter|
///
/// State-modifying layers should contain code similar to this pattern in both
/// their |Preroll| and |Paint| methods.
///
/// void [LayerType]::[Preroll/Paint](context) {
///   auto mutator = context.state_stack.save();
///   mutator.translate(origin.x, origin.y);
///   mutator.applyOpacity(content_bounds, opacity_value);
///   mutator.applyColorFilter(content_bounds, color_filter);
///   // or any of the mutator transform, clip or attribute methods
///
///   // Children will react to the state applied above during their
///   // Preroll/Paint methods or ContainerLayer will protect them
///   // conservatively by default.
///   [Preroll/Paint]Children(context);
///
///   // here the mutator will be auto-destructed and the state accumulated
///   // by it will be restored out of the state_stack and its associated
///   // delegates.
/// }
class LayerStateStack {
 public:
  LayerStateStack();

  // Clears out any old delegate to make room for a new one.
  void clear_delegate();

  // Return the DlCanvas delegate if the state stack has such a delegate.
  // The state stack will only have one delegate at a time holding either
  // a DlCanvas or a preroll accumulator.
  DlCanvas* canvas_delegate() { return delegate_->canvas(); }

  // Clears the old delegate and sets the canvas delegate to the indicated
  // DL canvas (if not nullptr). This ensures that only one delegate - either
  // a DlCanvas or a preroll accumulator - is present at any one time.
  void set_delegate(DlCanvas* canvas);

  // Clears the old delegate and sets the state stack up to accumulate
  // clip and transform information for a Preroll phase. This ensures
  // that only one delegate - either a DlCanvas or a preroll accumulator -
  // is present at any one time.
  void set_preroll_delegate(const SkRect& cull_rect, const SkMatrix& matrix);
  void set_preroll_delegate(const SkRect& cull_rect);
  void set_preroll_delegate(const SkMatrix& matrix);

  // Fills the supplied MatatorsStack object with the mutations recorded
  // by this LayerStateStack in the order encountered.
  void fill(MutatorsStack* mutators);

  // Sets up a checkerboard function that will be used to checkerboard the
  // contents of any saveLayer executed by the state stack.
  CheckerboardFunc checkerboard_func() const { return checkerboard_func_; }
  void set_checkerboard_func(CheckerboardFunc checkerboard_func) {
    checkerboard_func_ = checkerboard_func;
  }

  class AutoRestore {
   public:
    ~AutoRestore() {
      layer_state_stack_->restore_to_count(stack_restore_count_);
    }

   private:
    AutoRestore(LayerStateStack* stack, const SkRect& bounds, int flags)
        : layer_state_stack_(stack),
          stack_restore_count_(stack->stack_count()) {
      if (stack->needs_save_layer(flags)) {
        stack->save_layer(bounds);
      }
    }
    friend class LayerStateStack;

    LayerStateStack* layer_state_stack_;
    const size_t stack_restore_count_;

    FML_DISALLOW_COPY_ASSIGN_AND_MOVE(AutoRestore);
  };

  class MutatorContext {
   public:
    ~MutatorContext() {
      layer_state_stack_->restore_to_count(stack_restore_count_);
    }

    // Immediately executes a saveLayer with all accumulated state
    // onto the canvas or builder to be applied at the next matching
    // restore. A saveLayer is always executed by this method even if
    // there are no outstanding attributes.
    void saveLayer(const SkRect& bounds);

    // Records the opacity for application at the next call to
    // saveLayer or applyState. A saveLayer may be executed at
    // this time if the opacity cannot be batched with other
    // outstanding attributes.
    void applyOpacity(const SkRect& bounds, SkScalar opacity);

    // Records the image filter for application at the next call to
    // saveLayer or applyState. A saveLayer may be executed at
    // this time if the image filter cannot be batched with other
    // outstanding attributes.
    // (Currently only opacity is recorded for batching)
    void applyImageFilter(const SkRect& bounds,
                          const std::shared_ptr<const DlImageFilter>& filter);

    // Records the color filter for application at the next call to
    // saveLayer or applyState. A saveLayer may be executed at
    // this time if the color filter cannot be batched with other
    // outstanding attributes.
    // (Currently only opacity is recorded for batching)
    void applyColorFilter(const SkRect& bounds,
                          const std::shared_ptr<const DlColorFilter>& filter);

    // Saves the state stack and immediately executes a saveLayer
    // with the indicated backdrop filter and any outstanding
    // state attributes. Since the backdrop filter only applies
    // to the pixels alrady on the screen when this call is made,
    // the backdrop filter will only be applied to the canvas or
    // builder installed at the time that this call is made, and
    // subsequent canvas or builder objects that are made delegates
    // will only see a saveLayer with the indicated blend_mode.
    void applyBackdropFilter(const SkRect& bounds,
                             const std::shared_ptr<const DlImageFilter>& filter,
                             DlBlendMode blend_mode);

    void translate(SkScalar tx, SkScalar ty);
    void translate(SkPoint tp) { translate(tp.fX, tp.fY); }
    void transform(const SkM44& m44);
    void transform(const SkMatrix& matrix);
    void integralTransform();

    void clipRect(const SkRect& rect, bool is_aa);
    void clipRRect(const SkRRect& rrect, bool is_aa);
    void clipPath(const SkPath& path, bool is_aa);

   private:
    MutatorContext(LayerStateStack* stack)
        : layer_state_stack_(stack),
          stack_restore_count_(stack->stack_count()),
          save_needed_(true) {}
    friend class LayerStateStack;

    LayerStateStack* layer_state_stack_;
    const size_t stack_restore_count_;
    bool save_needed_;

    FML_DISALLOW_COPY_ASSIGN_AND_MOVE(MutatorContext);
  };

  static constexpr int kCallerCanApplyOpacity = 0x1;
  static constexpr int kCallerCanApplyColorFilter = 0x2;
  static constexpr int kCallerCanApplyImageFilter = 0x4;
  static constexpr int kCallerCanApplyAnything =
      (kCallerCanApplyOpacity | kCallerCanApplyColorFilter |
       kCallerCanApplyImageFilter);

  // Apply the outstanding state via saveLayer if necessary,
  // respecting the flags representing which potentially
  // outstanding attributes the calling layer can apply
  // themselves.
  //
  // A saveLayer may or may not be sent to the delegates depending
  // on how the outstanding state intersects with the flags supplied
  // by the caller.
  //
  // An AutoRestore instance will always be returned even if there
  // was no saveLayer applied.
  [[nodiscard]] inline AutoRestore applyState(const SkRect& bounds,
                                              int can_apply_flags) {
    return AutoRestore(this, bounds, can_apply_flags);
  }

  SkScalar outstanding_opacity() const { return outstanding_.opacity; }

  std::shared_ptr<const DlColorFilter> outstanding_color_filter() const {
    return outstanding_.color_filter;
  }

  std::shared_ptr<const DlImageFilter> outstanding_image_filter() const {
    return outstanding_.image_filter;
  }

  // The outstanding bounds are the bounds recorded during the last
  // attribute applied to this state stack. The assumption is that
  // the nested calls to the state stack will each supply bounds relative
  // to the content of that single attribute and the bounds of the content
  // of any outstanding attributes will include the output bounds of
  // applying any nested attributes. Thus, only the innermost content
  // bounds received will be sufficient to apply all outstanding attributes.
  SkRect outstanding_bounds() const { return outstanding_.save_layer_bounds; }

  // Fill the provided paint object with any oustanding attributes and
  // return a pointer to it, or return a nullptr if there were no
  // outstanding attributes to paint with.
  DlPaint* fill(DlPaint& paint) const { return outstanding_.fill(paint); }

  // The cull_rect (not the exact clip) relative to the device pixels.
  // This rectangle may be a conservative estimate of the true clip region.
  SkRect device_cull_rect() const { return delegate_->device_cull_rect(); }

  // The cull_rect (not the exact clip) relative to the local coordinates.
  // This rectangle may be a conservative estimate of the true clip region.
  SkRect local_cull_rect() const { return delegate_->local_cull_rect(); }

  // The transform from the local coordinates to the device coordinates
  // in the most capable 4x4 matrix representation. This matrix may be
  // more information than is needed to compute bounds for a 2D rendering
  // primitive, but it will accurately concatenate with other 4x4 matrices
  // without losing information.
  SkM44 transform_4x4() const { return delegate_->matrix_4x4(); }

  // The transform from the local coordinates to the device coordinates
  // in a more compact 3x3 matrix represenation that provides enough
  // information to accurately transform 2D primitives into their
  // resulting 2D bounds. This matrix also has enough information to
  // concat with other 2D affine transforms, but does not carry enough
  // information to accurately concat with fully perspective matrics.
  SkMatrix transform_3x3() const { return delegate_->matrix_3x3(); }

  // Tests if painting content with the current outstanding attributes
  // will produce any content. This method does not check the current
  // transform or clip for being singular or empty.
  // See |content_culled|
  bool painting_is_nop() const { return outstanding_.opacity <= 0; }

  // Tests if painting content with the given bounds will produce any output.
  // This method does not check the outstanding attributes to verify that
  // they produce visible results.
  // See |painting_is_nop|
  bool content_culled(const SkRect& content_bounds) const {
    return delegate_->content_culled(content_bounds);
  }

  // Saves the current state of the state stack and returns a
  // MutatorContext which can be used to manipulate the state.
  // The state stack will be restored to its current state
  // when the MutatorContext object goes out of scope.
  [[nodiscard]] inline MutatorContext save() { return MutatorContext(this); }

  // Returns true if the state stack is in, or has returned to,
  // its initial state.
  bool is_empty() const { return state_stack_.empty(); }

 private:
  size_t stack_count() const { return state_stack_.size(); }
  void restore_to_count(size_t restore_count);
  void reapply_all();

  void apply_last_entry() { state_stack_.back()->apply(this); }

  // The push methods simply push an associated StateEntry on the stack
  // and then apply it to the current canvas and builder.
  // ---------------------
  // void push_attributes();
  void push_opacity(const SkRect& rect, SkScalar opacity);
  void push_color_filter(const SkRect& bounds,
                         const std::shared_ptr<const DlColorFilter>& filter);
  void push_image_filter(const SkRect& bounds,
                         const std::shared_ptr<const DlImageFilter>& filter);
  void push_backdrop(const SkRect& bounds,
                     const std::shared_ptr<const DlImageFilter>& filter,
                     DlBlendMode blend_mode);

  void push_translate(SkScalar tx, SkScalar ty);
  void push_transform(const SkM44& matrix);
  void push_transform(const SkMatrix& matrix);
  void push_integral_transform();

  void push_clip_rect(const SkRect& rect, bool is_aa);
  void push_clip_rrect(const SkRRect& rrect, bool is_aa);
  void push_clip_path(const SkPath& path, bool is_aa);
  // ---------------------

  // The maybe/needs_save_layer methods will determine if the indicated
  // attribute can be incorporated into the outstanding attributes as is,
  // or if the apply_flags are compatible with the outstanding attributes.
  // If the oustanding attributes are incompatible with the new attribute
  // or the apply flags, then a protective saveLayer will be executed.
  // ---------------------
  bool needs_save_layer(int flags) const;
  void do_save();
  void save_layer(const SkRect& bounds);
  void maybe_save_layer_for_transform(bool needs_save);
  void maybe_save_layer_for_clip(bool needs_save);
  void maybe_save_layer(int apply_flags);
  void maybe_save_layer(SkScalar opacity);
  void maybe_save_layer(const std::shared_ptr<const DlColorFilter>& filter);
  void maybe_save_layer(const std::shared_ptr<const DlImageFilter>& filter);
  // ---------------------

  struct RenderingAttributes {
    // We need to record the last bounds we received for the last
    // attribute that we recorded so that we can perform a saveLayer
    // on the proper area. When an attribute is applied that cannot
    // be merged with the existing attributes, it will be submitted
    // with a bounds for its own source content, not the bounds for
    // the content that will be included in the saveLayer that applies
    // the existing outstanding attributes - thus we need to record
    // the bounds that were supplied with the most recent previous
    // attribute to be applied.
    SkRect save_layer_bounds{0, 0, 0, 0};

    SkScalar opacity = SK_Scalar1;
    std::shared_ptr<const DlColorFilter> color_filter;
    std::shared_ptr<const DlImageFilter> image_filter;

    DlPaint* fill(DlPaint& paint,
                  DlBlendMode mode = DlBlendMode::kSrcOver) const;

    bool operator==(const RenderingAttributes& other) const {
      return save_layer_bounds == other.save_layer_bounds &&
             opacity == other.opacity &&
             Equals(color_filter, other.color_filter) &&
             Equals(image_filter, other.image_filter);
    }
  };

  class StateEntry {
   public:
    virtual ~StateEntry() = default;

    virtual void apply(LayerStateStack* stack) const = 0;
    virtual void reapply(LayerStateStack* stack) const { apply(stack); }
    virtual void restore(LayerStateStack* stack) const {}
    virtual void update_mutators(MutatorsStack* mutators_stack) const {}

   protected:
    StateEntry() = default;

    FML_DISALLOW_COPY_ASSIGN_AND_MOVE(StateEntry);
  };
  friend class SaveEntry;
  friend class SaveLayerEntry;
  friend class BackdropFilterEntry;
  friend class OpacityEntry;
  friend class ImageFilterEntry;
  friend class ColorFilterEntry;
  friend class TranslateEntry;
  friend class TransformMatrixEntry;
  friend class TransformM44Entry;
  friend class IntegralTransformEntry;
  friend class ClipEntry;
  friend class ClipRectEntry;
  friend class ClipRRectEntry;
  friend class ClipPathEntry;

  class Delegate {
   protected:
    using ClipOp = DlCanvas::ClipOp;

   public:
    virtual ~Delegate() = default;

    // Mormally when a |Paint| or |Preroll| cycle is completed, the
    // delegate will have been rewound to its initial state by the
    // trailing recursive actions of the paint and preroll methods.
    // When a delegate is swapped out, there may be unresolved state
    // that the delegate received. This method is called when the
    // delegate is cleared or swapped out to inform it to rewind its
    // state and finalize all outstanding save or saveLayer operations.
    virtual void decommission() = 0;

    virtual DlCanvas* canvas() const { return nullptr; }

    virtual SkRect local_cull_rect() const = 0;
    virtual SkRect device_cull_rect() const = 0;
    virtual SkM44 matrix_4x4() const = 0;
    virtual SkMatrix matrix_3x3() const = 0;
    virtual bool content_culled(const SkRect& content_bounds) const = 0;

    virtual void save() = 0;
    virtual void saveLayer(const SkRect& bounds,
                           RenderingAttributes& attributes,
                           DlBlendMode blend,
                           const DlImageFilter* backdrop) = 0;
    virtual void restore() = 0;

    virtual void translate(SkScalar tx, SkScalar ty) = 0;
    virtual void transform(const SkM44& m44) = 0;
    virtual void transform(const SkMatrix& matrix) = 0;
    virtual void integralTransform() = 0;

    virtual void clipRect(const SkRect& rect, ClipOp op, bool is_aa) = 0;
    virtual void clipRRect(const SkRRect& rrect, ClipOp op, bool is_aa) = 0;
    virtual void clipPath(const SkPath& path, ClipOp op, bool is_aa) = 0;
  };
  friend class DummyDelegate;
  friend class DlCanvasDelegate;
  friend class PrerollDelegate;

  std::vector<std::unique_ptr<StateEntry>> state_stack_;
  friend class MutatorContext;

  std::shared_ptr<Delegate> delegate_;
  RenderingAttributes outstanding_;
  CheckerboardFunc checkerboard_func_ = nullptr;

  friend class SaveLayerEntry;
};

}  // namespace flutter

#endif  // FLUTTER_FLOW_LAYERS_LAYER_STATE_STACK_H_
