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

#if !SLIMPELLER

#include "flutter/display_list/skia/dl_sk_canvas.h"

#include "flutter/display_list/skia/dl_sk_conversions.h"
#include "flutter/display_list/skia/dl_sk_dispatcher.h"
#include "flutter/fml/trace_event.h"

#include "third_party/skia/include/core/SkColorFilter.h"
#include "third_party/skia/include/gpu/GrDirectContext.h"
#include "third_party/skia/include/gpu/GrRecordingContext.h"

namespace flutter {

class SkOptionalPaint {
 public:
  // SkOptionalPaint is only valid for ops that do not use the ColorSource
  explicit SkOptionalPaint(const DlPaint* dl_paint) {
    if (dl_paint && !dl_paint->isDefault()) {
      sk_paint_ = ToNonShaderSk(*dl_paint);
      ptr_ = &sk_paint_;
    } else {
      ptr_ = nullptr;
    }
  }

  SkPaint* operator()() { return ptr_; }

 private:
  SkPaint sk_paint_;
  SkPaint* ptr_;
};

void DlSkCanvasAdapter::set_canvas(SkCanvas* canvas) {
  delegate_ = canvas;
}

SkISize DlSkCanvasAdapter::GetBaseLayerSize() const {
  return delegate_->getBaseLayerSize();
}

SkImageInfo DlSkCanvasAdapter::GetImageInfo() const {
  return delegate_->imageInfo();
}

void DlSkCanvasAdapter::Save() {
  delegate_->save();
}

void DlSkCanvasAdapter::SaveLayer(const SkRect* bounds,
                                  const DlPaint* paint,
                                  const DlImageFilter* backdrop) {
  sk_sp<SkImageFilter> sk_backdrop = ToSk(backdrop);
  SkOptionalPaint sk_paint(paint);
  TRACE_EVENT0("flutter", "Canvas::saveLayer");
  delegate_->saveLayer(
      SkCanvas::SaveLayerRec{bounds, sk_paint(), sk_backdrop.get(), 0});
}

void DlSkCanvasAdapter::Restore() {
  delegate_->restore();
}

int DlSkCanvasAdapter::GetSaveCount() const {
  return delegate_->getSaveCount();
}

void DlSkCanvasAdapter::RestoreToCount(int restore_count) {
  delegate_->restoreToCount(restore_count);
}

void DlSkCanvasAdapter::Translate(SkScalar tx, SkScalar ty) {
  delegate_->translate(tx, ty);
}

void DlSkCanvasAdapter::Scale(SkScalar sx, SkScalar sy) {
  delegate_->scale(sx, sy);
}

void DlSkCanvasAdapter::Rotate(SkScalar degrees) {
  delegate_->rotate(degrees);
}

void DlSkCanvasAdapter::Skew(SkScalar sx, SkScalar sy) {
  delegate_->skew(sx, sy);
}

// clang-format off

// 2x3 2D affine subset of a 4x4 transform in row major order
void DlSkCanvasAdapter::Transform2DAffine(
    SkScalar mxx, SkScalar mxy, SkScalar mxt,
    SkScalar myx, SkScalar myy, SkScalar myt) {
  delegate_->concat(SkMatrix::MakeAll(mxx, mxy, mxt, myx, myy, myt, 0, 0, 1));
}

// full 4x4 transform in row major order
void DlSkCanvasAdapter::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) {
  delegate_->concat(SkM44(mxx, mxy, mxz, mxt,
                          myx, myy, myz, myt,
                          mzx, mzy, mzz, mzt,
                          mwx, mwy, mwz, mwt));
}

// clang-format on

void DlSkCanvasAdapter::TransformReset() {
  delegate_->resetMatrix();
}

void DlSkCanvasAdapter::Transform(const SkMatrix* matrix) {
  delegate_->concat(*matrix);
}

void DlSkCanvasAdapter::Transform(const SkM44* matrix44) {
  delegate_->concat(*matrix44);
}

void DlSkCanvasAdapter::SetTransform(const SkMatrix* matrix) {
  delegate_->setMatrix(*matrix);
}

void DlSkCanvasAdapter::SetTransform(const SkM44* matrix44) {
  delegate_->setMatrix(*matrix44);
}

/// Returns the 4x4 full perspective transform representing all transform
/// operations executed so far in this DisplayList within the enclosing
/// save stack.
SkM44 DlSkCanvasAdapter::GetTransformFullPerspective() const {
  return delegate_->getLocalToDevice();
}

/// Returns the 3x3 partial perspective transform representing all transform
/// operations executed so far in this DisplayList within the enclosing
/// save stack.
SkMatrix DlSkCanvasAdapter::GetTransform() const {
  return delegate_->getTotalMatrix();
}

void DlSkCanvasAdapter::ClipRect(const SkRect& rect,
                                 ClipOp clip_op,
                                 bool is_aa) {
  delegate_->clipRect(rect, ToSk(clip_op), is_aa);
}

void DlSkCanvasAdapter::ClipRRect(const SkRRect& rrect,
                                  ClipOp clip_op,
                                  bool is_aa) {
  delegate_->clipRRect(rrect, ToSk(clip_op), is_aa);
}

void DlSkCanvasAdapter::ClipPath(const SkPath& path,
                                 ClipOp clip_op,
                                 bool is_aa) {
  delegate_->clipPath(path, ToSk(clip_op), is_aa);
}

/// Conservative estimate of the bounds of all outstanding clip operations
/// measured in the coordinate space within which this DisplayList will
/// be rendered.
SkRect DlSkCanvasAdapter::GetDestinationClipBounds() const {
  return SkRect::Make(delegate_->getDeviceClipBounds());
}

/// Conservative estimate of the bounds of all outstanding clip operations
/// transformed into the local coordinate space in which currently
/// recorded rendering operations are interpreted.
SkRect DlSkCanvasAdapter::GetLocalClipBounds() const {
  return delegate_->getLocalClipBounds();
}

/// Return true iff the supplied bounds are easily shown to be outside
/// of the current clip bounds. This method may conservatively return
/// false if it cannot make the determination.
bool DlSkCanvasAdapter::QuickReject(const SkRect& bounds) const {
  return delegate_->quickReject(bounds);
}

void DlSkCanvasAdapter::DrawPaint(const DlPaint& paint) {
  delegate_->drawPaint(ToSk(paint));
}

void DlSkCanvasAdapter::DrawColor(DlColor color, DlBlendMode mode) {
  delegate_->drawColor(ToSk(color), ToSk(mode));
}

void DlSkCanvasAdapter::DrawLine(const SkPoint& p0,
                                 const SkPoint& p1,
                                 const DlPaint& paint) {
  delegate_->drawLine(p0, p1, ToStrokedSk(paint));
}

void DlSkCanvasAdapter::DrawRect(const SkRect& rect, const DlPaint& paint) {
  delegate_->drawRect(rect, ToSk(paint));
}

void DlSkCanvasAdapter::DrawOval(const SkRect& bounds, const DlPaint& paint) {
  delegate_->drawOval(bounds, ToSk(paint));
}

void DlSkCanvasAdapter::DrawCircle(const SkPoint& center,
                                   SkScalar radius,
                                   const DlPaint& paint) {
  delegate_->drawCircle(center, radius, ToSk(paint));
}

void DlSkCanvasAdapter::DrawRRect(const SkRRect& rrect, const DlPaint& paint) {
  delegate_->drawRRect(rrect, ToSk(paint));
}

void DlSkCanvasAdapter::DrawDRRect(const SkRRect& outer,
                                   const SkRRect& inner,
                                   const DlPaint& paint) {
  delegate_->drawDRRect(outer, inner, ToSk(paint));
}

void DlSkCanvasAdapter::DrawPath(const SkPath& path, const DlPaint& paint) {
  delegate_->drawPath(path, ToSk(paint));
}

void DlSkCanvasAdapter::DrawArc(const SkRect& bounds,
                                SkScalar start,
                                SkScalar sweep,
                                bool useCenter,
                                const DlPaint& paint) {
  delegate_->drawArc(bounds, start, sweep, useCenter, ToSk(paint));
}

void DlSkCanvasAdapter::DrawPoints(PointMode mode,
                                   uint32_t count,
                                   const SkPoint pts[],
                                   const DlPaint& paint) {
  delegate_->drawPoints(ToSk(mode), count, pts, ToStrokedSk(paint));
}

void DlSkCanvasAdapter::DrawVertices(const DlVertices* vertices,
                                     DlBlendMode mode,
                                     const DlPaint& paint) {
  delegate_->drawVertices(ToSk(vertices), ToSk(mode), ToSk(paint));
}

void DlSkCanvasAdapter::DrawImage(const sk_sp<DlImage>& image,
                                  const SkPoint point,
                                  DlImageSampling sampling,
                                  const DlPaint* paint) {
  SkOptionalPaint sk_paint(paint);
  sk_sp<SkImage> sk_image = image->skia_image();
  delegate_->drawImage(sk_image.get(), point.fX, point.fY, ToSk(sampling),
                       sk_paint());
}

void DlSkCanvasAdapter::DrawImageRect(const sk_sp<DlImage>& image,
                                      const SkRect& src,
                                      const SkRect& dst,
                                      DlImageSampling sampling,
                                      const DlPaint* paint,
                                      SrcRectConstraint constraint) {
  SkOptionalPaint sk_paint(paint);
  sk_sp<SkImage> sk_image = image->skia_image();
  delegate_->drawImageRect(sk_image.get(), src, dst, ToSk(sampling), sk_paint(),
                           ToSk(constraint));
}

void DlSkCanvasAdapter::DrawImageNine(const sk_sp<DlImage>& image,
                                      const SkIRect& center,
                                      const SkRect& dst,
                                      DlFilterMode filter,
                                      const DlPaint* paint) {
  SkOptionalPaint sk_paint(paint);
  sk_sp<SkImage> sk_image = image->skia_image();
  delegate_->drawImageNine(sk_image.get(), center, dst, ToSk(filter),
                           sk_paint());
}

void DlSkCanvasAdapter::DrawAtlas(const sk_sp<DlImage>& atlas,
                                  const SkRSXform xform[],
                                  const SkRect tex[],
                                  const DlColor colors[],
                                  int count,
                                  DlBlendMode mode,
                                  DlImageSampling sampling,
                                  const SkRect* cullRect,
                                  const DlPaint* paint) {
  SkOptionalPaint sk_paint(paint);
  sk_sp<SkImage> sk_image = atlas->skia_image();
  const SkColor* sk_colors = reinterpret_cast<const SkColor*>(colors);
  delegate_->drawAtlas(sk_image.get(), xform, tex, sk_colors, count, ToSk(mode),
                       ToSk(sampling), cullRect, sk_paint());
}

void DlSkCanvasAdapter::DrawDisplayList(const sk_sp<DisplayList> display_list,
                                        SkScalar opacity) {
  const int restore_count = delegate_->getSaveCount();

  // Figure out whether we can apply the opacity during dispatch or
  // if we need a saveLayer.
  if (opacity < SK_Scalar1 && !display_list->can_apply_group_opacity()) {
    TRACE_EVENT0("flutter", "Canvas::saveLayer");
    delegate_->saveLayerAlphaf(&display_list->bounds(), opacity);
    opacity = SK_Scalar1;
  } else {
    delegate_->save();
  }

  DlSkCanvasDispatcher dispatcher(delegate_, opacity);
  if (display_list->has_rtree()) {
    display_list->Dispatch(dispatcher, delegate_->getLocalClipBounds());
  } else {
    display_list->Dispatch(dispatcher);
  }

  delegate_->restoreToCount(restore_count);
}

void DlSkCanvasAdapter::DrawTextBlob(const sk_sp<SkTextBlob>& blob,
                                     SkScalar x,
                                     SkScalar y,
                                     const DlPaint& paint) {
  delegate_->drawTextBlob(blob, x, y, ToSk(paint));
}

void DlSkCanvasAdapter::DrawTextFrame(
    const std::shared_ptr<impeller::TextFrame>& text_frame,
    SkScalar x,
    SkScalar y,
    const DlPaint& paint) {
  FML_CHECK(false);
}

void DlSkCanvasAdapter::DrawShadow(const SkPath& path,
                                   const DlColor color,
                                   const SkScalar elevation,
                                   bool transparent_occluder,
                                   SkScalar dpr) {
  DlSkCanvasDispatcher::DrawShadow(delegate_, path, color, elevation,
                                   transparent_occluder, dpr);
}

void DlSkCanvasAdapter::Flush() {
  auto dContext = GrAsDirectContext(delegate_->recordingContext());

  if (dContext) {
    dContext->flushAndSubmit();
  }
}

}  // namespace flutter

#endif  //  !SLIMPELLER
