// 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_PATH_EFFECT_H_
#define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_PATH_EFFECT_H_

#include <cstring>
#include <optional>
#include "flutter/display_list/display_list_attributes.h"
#include "flutter/display_list/types.h"
#include "flutter/fml/logging.h"
#include "include/core/SkScalar.h"

namespace flutter {

class DlDashPathEffect;

// The DisplayList PathEffect class. This class implements all of the
// facilities and adheres to the design goals of the |DlAttribute| base
// class.

// An enumerated type for the supported PathEffect operations.
enum class DlPathEffectType {
  kDash,
};

class DlPathEffect : public DlAttribute<DlPathEffect, DlPathEffectType> {
 public:
  virtual const DlDashPathEffect* asDash() const { return nullptr; }

  virtual std::optional<SkRect> effect_bounds(SkRect&) const = 0;

 protected:
  DlPathEffect() = default;

 private:
  FML_DISALLOW_COPY_ASSIGN_AND_MOVE(DlPathEffect);
};

/// The DashPathEffect which breaks a path up into dash segments, and it
/// only affects stroked paths.
/// intervals: array containing an even number of entries (>=2), with
/// the even indices specifying the length of "on" intervals, and the odd
/// indices specifying the length of "off" intervals. This array will be
/// copied in Make, and can be disposed of freely after.
/// count: number of elements in the intervals array.
/// phase: initial distance into the intervals at which to start the dashing
/// effect for the path.
///
/// For example: if intervals[] = {10, 20}, count = 2, and phase = 25,
/// this will set up a dashed path like so:
/// 5 pixels off
/// 10 pixels on
/// 20 pixels off
/// 10 pixels on
/// 20 pixels off
/// ...
/// A phase of -5, 25, 55, 85, etc. would all result in the same path,
/// because the sum of all the intervals is 30.
///
class DlDashPathEffect final : public DlPathEffect {
 public:
  static std::shared_ptr<DlPathEffect> Make(const SkScalar intervals[],
                                            int count,
                                            SkScalar phase);

  DlPathEffectType type() const override { return DlPathEffectType::kDash; }
  size_t size() const override {
    return sizeof(*this) + sizeof(SkScalar) * count_;
  }

  std::shared_ptr<DlPathEffect> shared() const override {
    return Make(intervals(), count_, phase_);
  }

  const DlDashPathEffect* asDash() const override { return this; }

  const SkScalar* intervals() const {
    return reinterpret_cast<const SkScalar*>(this + 1);
  }
  int count() const { return count_; }
  SkScalar phase() const { return phase_; }

  std::optional<SkRect> effect_bounds(SkRect& rect) const override;

 protected:
  bool equals_(DlPathEffect const& other) const override {
    FML_DCHECK(other.type() == DlPathEffectType::kDash);
    auto that = static_cast<DlDashPathEffect const*>(&other);
    return count_ == that->count_ && phase_ == that->phase_ &&
           memcmp(intervals(), that->intervals(), sizeof(SkScalar) * count_) ==
               0;
  }

 private:
  // DlDashPathEffect constructor assumes the caller has prealloced storage for
  // the intervals. If the intervals is nullptr the intervals will
  // uninitialized.
  DlDashPathEffect(const SkScalar intervals[], int count, SkScalar phase)
      : count_(count), phase_(phase) {
    if (intervals != nullptr) {
      SkScalar* intervals_ = reinterpret_cast<SkScalar*>(this + 1);
      memcpy(intervals_, intervals, sizeof(SkScalar) * count);
    }
  }

  DlDashPathEffect(const DlDashPathEffect* dash_effect)
      : DlDashPathEffect(dash_effect->intervals(),
                         dash_effect->count_,
                         dash_effect->phase_) {}

  SkScalar* intervals_unsafe() { return reinterpret_cast<SkScalar*>(this + 1); }

  int count_;
  SkScalar phase_;

  friend class DisplayListBuilder;
  friend class DlPathEffect;

  FML_DISALLOW_COPY_ASSIGN_AND_MOVE(DlDashPathEffect);
};

}  // namespace flutter

#endif  // FLUTTER_DISPLAY_LIST_DISPLAY_LIST_PATH_EFFECT_H_
