// LAF Gfx Library
// Copyright (c) 2020-2023  Igara Studio S.A.
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.

#ifndef GFX_PATH_SKIA_H_INCLUDED
#define GFX_PATH_SKIA_H_INCLUDED
#pragma once

#include "gfx/matrix.h"
#include "gfx/point.h"
#include "gfx/rect.h"

#include "include/core/SkPath.h"

#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4244) // 'argument': conversion from 'T' to 'SkScalar', possible loss of data
#endif

namespace gfx {

  // Simple wrapper for SkPath
  // TODO add missing methods for curves
  class Path {
  public:
    Path() { }

    Path& reset() {
      m_skPath.reset();
      return *this;
    }

    Path& rewind() {
      m_skPath.rewind();
      return *this;
    }

    bool isEmpty() const {
      return m_skPath.isEmpty();
    }

    Path& moveTo(float x, float y) {
      m_skPath.moveTo(x, y);
      return *this;
    }

    Path& moveTo(const Point& p) {
      m_skPath.moveTo(p.x, p.y);
      return *this;
    }

    Path& lineTo(float x, float y) {
      m_skPath.lineTo(x, y);
      return *this;
    }

    Path& lineTo(const Point& p) {
      m_skPath.lineTo(p.x, p.y);
      return *this;
    }

    Path& cubicTo(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3) {
      m_skPath.cubicTo(dx1, dy1, dx2, dy2, dx3, dy3);
      return *this;
    }

    Path& oval(const Rect& rc) {
      m_skPath.addOval(SkRect::MakeXYWH(rc.x, rc.y, rc.w, rc.h));
      return *this;
    }

    Path& rect(const Rect& rc) {
      m_skPath.addRect(SkRect::MakeXYWH(rc.x, rc.y, rc.w, rc.h));
      return *this;
    }

    Path& roundedRect(const Rect& rc, float rx, float ry) {
      m_skPath.addRoundRect(SkRect::MakeXYWH(rc.x+0.5, rc.y+0.5, rc.w, rc.h), rx, ry);
      return *this;
    }

    Path& close() {
      m_skPath.close();
      return *this;
    }

    void offset(float dx, float dy, Path* dst) const {
      m_skPath.offset(dx, dy, &dst->m_skPath);
    }

    void offset(float dx, float dy) {
      m_skPath.offset(dx, dy);
    }

    void transform(const Matrix& matrix, Path* dst) {
      m_skPath.transform(matrix.skMatrix(), &dst->m_skPath);
    }

    void transform(const Matrix& matrix) {
      m_skPath.transform(matrix.skMatrix());
    }

    RectF bounds() const {
      if (isEmpty())
        return RectF();

      SkRect rc = m_skPath.computeTightBounds();
      return RectF(rc.x(), rc.y(), rc.width(), rc.height());
    }

    const SkPath& skPath() const { return m_skPath; }
    SkPath& skPath() { return m_skPath; }

  private:
    SkPath m_skPath;
  };

} // namespace gfx

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#endif
