// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "cc/paint/record_paint_canvas.h"

#include "cc/paint/display_item_list.h"
#include "cc/paint/paint_image_builder.h"
#include "cc/paint/paint_record.h"
#include "cc/paint/paint_recorder.h"
#include "cc/paint/skottie_wrapper.h"
#include "third_party/skia/include/core/SkAnnotation.h"
#include "third_party/skia/include/core/SkMetaData.h"
#include "third_party/skia/include/utils/SkNWayCanvas.h"

namespace cc {

RecordPaintCanvas::RecordPaintCanvas(DisplayItemList* list,
                                     const SkRect& bounds)
    : list_(list), recording_bounds_(bounds) {
  DCHECK(list_);
}

RecordPaintCanvas::~RecordPaintCanvas() = default;

SkMetaData& RecordPaintCanvas::getMetaData() {
  // This could just be SkMetaData owned by RecordPaintCanvas, but since
  // SkCanvas already has one, we might as well use it directly.
  return GetCanvas()->getMetaData();
}

SkImageInfo RecordPaintCanvas::imageInfo() const {
  return GetCanvas()->imageInfo();
}

void RecordPaintCanvas::flush() {
  // This is a noop when recording.
}

int RecordPaintCanvas::save() {
  list_->push<SaveOp>();
  return GetCanvas()->save();
}

int RecordPaintCanvas::saveLayer(const SkRect* bounds,
                                 const PaintFlags* flags) {
  if (flags) {
    if (flags->IsSimpleOpacity()) {
      // TODO(enne): maybe more callers should know this and call
      // saveLayerAlpha instead of needing to check here.
      uint8_t alpha = SkColorGetA(flags->getColor());
      return saveLayerAlpha(bounds, alpha);
    }

    // TODO(enne): it appears that image filters affect matrices and color
    // matrices affect transparent flags on SkCanvas layers, but it's not clear
    // whether those are actually needed and we could just skip ToSkPaint here.
    list_->push<SaveLayerOp>(bounds, flags);
    SkPaint paint = flags->ToSkPaint();
    return GetCanvas()->saveLayer(bounds, &paint);
  }
  list_->push<SaveLayerOp>(bounds, flags);
  return GetCanvas()->saveLayer(bounds, nullptr);
}

int RecordPaintCanvas::saveLayerAlpha(const SkRect* bounds, uint8_t alpha) {
  list_->push<SaveLayerAlphaOp>(bounds, alpha);
  return GetCanvas()->saveLayerAlpha(bounds, alpha);
}

void RecordPaintCanvas::restore() {
  list_->push<RestoreOp>();
  GetCanvas()->restore();
}

int RecordPaintCanvas::getSaveCount() const {
  return GetCanvas()->getSaveCount();
}

void RecordPaintCanvas::restoreToCount(int save_count) {
  if (!canvas_) {
    DCHECK_EQ(save_count, 1);
    return;
  }

  DCHECK_GE(save_count, 1);
  int diff = GetCanvas()->getSaveCount() - save_count;
  DCHECK_GE(diff, 0);
  for (int i = 0; i < diff; ++i)
    restore();
}

void RecordPaintCanvas::translate(SkScalar dx, SkScalar dy) {
  list_->push<TranslateOp>(dx, dy);
  GetCanvas()->translate(dx, dy);
}

void RecordPaintCanvas::scale(SkScalar sx, SkScalar sy) {
  list_->push<ScaleOp>(sx, sy);
  GetCanvas()->scale(sx, sy);
}

void RecordPaintCanvas::rotate(SkScalar degrees) {
  list_->push<RotateOp>(degrees);
  GetCanvas()->rotate(degrees);
}

void RecordPaintCanvas::concat(const SkMatrix& matrix) {
  list_->push<ConcatOp>(matrix);
  GetCanvas()->concat(matrix);
}

void RecordPaintCanvas::setMatrix(const SkMatrix& matrix) {
  list_->push<SetMatrixOp>(matrix);
  GetCanvas()->setMatrix(matrix);
}

void RecordPaintCanvas::clipRect(const SkRect& rect,
                                 SkClipOp op,
                                 bool antialias) {
  list_->push<ClipRectOp>(rect, op, antialias);
  GetCanvas()->clipRect(rect, op, antialias);
}

void RecordPaintCanvas::clipRRect(const SkRRect& rrect,
                                  SkClipOp op,
                                  bool antialias) {
  // TODO(enne): does this happen? Should the caller know this?
  if (rrect.isRect()) {
    clipRect(rrect.getBounds(), op, antialias);
    return;
  }
  list_->push<ClipRRectOp>(rrect, op, antialias);
  GetCanvas()->clipRRect(rrect, op, antialias);
}

void RecordPaintCanvas::clipPath(const SkPath& path,
                                 SkClipOp op,
                                 bool antialias) {
  if (!path.isInverseFillType() &&
      GetCanvas()->getTotalMatrix().rectStaysRect()) {
    // TODO(enne): do these cases happen? should the caller know that this isn't
    // a path?
    SkRect rect;
    if (path.isRect(&rect)) {
      clipRect(rect, op, antialias);
      return;
    }
    SkRRect rrect;
    if (path.isOval(&rect)) {
      rrect.setOval(rect);
      clipRRect(rrect, op, antialias);
      return;
    }
    if (path.isRRect(&rrect)) {
      clipRRect(rrect, op, antialias);
      return;
    }
  }

  list_->push<ClipPathOp>(path, op, antialias);
  GetCanvas()->clipPath(path, op, antialias);
  return;
}

SkRect RecordPaintCanvas::getLocalClipBounds() const {
  DCHECK(InitializedWithRecordingBounds());
  return GetCanvas()->getLocalClipBounds();
}

bool RecordPaintCanvas::getLocalClipBounds(SkRect* bounds) const {
  DCHECK(InitializedWithRecordingBounds());
  return GetCanvas()->getLocalClipBounds(bounds);
}

SkIRect RecordPaintCanvas::getDeviceClipBounds() const {
  DCHECK(InitializedWithRecordingBounds());
  return GetCanvas()->getDeviceClipBounds();
}

bool RecordPaintCanvas::getDeviceClipBounds(SkIRect* bounds) const {
  DCHECK(InitializedWithRecordingBounds());
  return GetCanvas()->getDeviceClipBounds(bounds);
}

void RecordPaintCanvas::drawColor(SkColor color, SkBlendMode mode) {
  list_->push<DrawColorOp>(color, mode);
}

void RecordPaintCanvas::clear(SkColor color) {
  list_->push<DrawColorOp>(color, SkBlendMode::kSrc);
}

void RecordPaintCanvas::drawLine(SkScalar x0,
                                 SkScalar y0,
                                 SkScalar x1,
                                 SkScalar y1,
                                 const PaintFlags& flags) {
  list_->push<DrawLineOp>(x0, y0, x1, y1, flags);
}

void RecordPaintCanvas::drawRect(const SkRect& rect, const PaintFlags& flags) {
  list_->push<DrawRectOp>(rect, flags);
}

void RecordPaintCanvas::drawIRect(const SkIRect& rect,
                                  const PaintFlags& flags) {
  list_->push<DrawIRectOp>(rect, flags);
}

void RecordPaintCanvas::drawOval(const SkRect& oval, const PaintFlags& flags) {
  list_->push<DrawOvalOp>(oval, flags);
}

void RecordPaintCanvas::drawRRect(const SkRRect& rrect,
                                  const PaintFlags& flags) {
  list_->push<DrawRRectOp>(rrect, flags);
}

void RecordPaintCanvas::drawDRRect(const SkRRect& outer,
                                   const SkRRect& inner,
                                   const PaintFlags& flags) {
  if (outer.isEmpty())
    return;
  if (inner.isEmpty()) {
    drawRRect(outer, flags);
    return;
  }
  list_->push<DrawDRRectOp>(outer, inner, flags);
}

void RecordPaintCanvas::drawRoundRect(const SkRect& rect,
                                      SkScalar rx,
                                      SkScalar ry,
                                      const PaintFlags& flags) {
  // TODO(enne): move this into base class?
  if (rx > 0 && ry > 0) {
    SkRRect rrect;
    rrect.setRectXY(rect, rx, ry);
    drawRRect(rrect, flags);
  } else {
    drawRect(rect, flags);
  }
}

void RecordPaintCanvas::drawPath(const SkPath& path, const PaintFlags& flags) {
  list_->push<DrawPathOp>(path, flags);
}

void RecordPaintCanvas::drawImage(const PaintImage& image,
                                  SkScalar left,
                                  SkScalar top,
                                  const PaintFlags* flags) {
  list_->push<DrawImageOp>(image, left, top, flags);
}

void RecordPaintCanvas::drawImageRect(const PaintImage& image,
                                      const SkRect& src,
                                      const SkRect& dst,
                                      const PaintFlags* flags,
                                      SrcRectConstraint constraint) {
  list_->push<DrawImageRectOp>(image, src, dst, flags, constraint);
}

void RecordPaintCanvas::drawSkottie(scoped_refptr<SkottieWrapper> skottie,
                                    const SkRect& dst,
                                    float t) {
  list_->push<DrawSkottieOp>(std::move(skottie), dst, t);
}

void RecordPaintCanvas::drawTextBlob(sk_sp<SkTextBlob> blob,
                                     SkScalar x,
                                     SkScalar y,
                                     const PaintFlags& flags) {
  list_->push<DrawTextBlobOp>(std::move(blob), x, y, flags);
}

void RecordPaintCanvas::drawPicture(sk_sp<const PaintRecord> record) {
  // TODO(enne): If this is small, maybe flatten it?
  list_->push<DrawRecordOp>(record);
}

bool RecordPaintCanvas::isClipEmpty() const {
  DCHECK(InitializedWithRecordingBounds());
  return GetCanvas()->isClipEmpty();
}

bool RecordPaintCanvas::isClipRect() const {
  DCHECK(InitializedWithRecordingBounds());
  return GetCanvas()->isClipRect();
}

const SkMatrix& RecordPaintCanvas::getTotalMatrix() const {
  return GetCanvas()->getTotalMatrix();
}

void RecordPaintCanvas::Annotate(AnnotationType type,
                                 const SkRect& rect,
                                 sk_sp<SkData> data) {
  list_->push<AnnotateOp>(type, rect, data);
}

void RecordPaintCanvas::recordCustomData(uint32_t id) {
  list_->push<CustomDataOp>(id);
}

const SkNoDrawCanvas* RecordPaintCanvas::GetCanvas() const {
  return const_cast<RecordPaintCanvas*>(this)->GetCanvas();
}

SkNoDrawCanvas* RecordPaintCanvas::GetCanvas() {
  if (canvas_)
    return &*canvas_;

  // Size the canvas to be large enough to contain the |recording_bounds|, which
  // may not be positioned at the origin.
  SkIRect enclosing_rect = recording_bounds_.roundOut();
  canvas_.emplace(enclosing_rect.right(), enclosing_rect.bottom());

  // This is part of the "recording canvases have a size, but why" dance.
  // By creating a canvas of size (right x bottom) and then clipping it,
  // It makes getDeviceClipBounds return the original cull rect, which code
  // in GraphicsContextCanvas on Mac expects.  (Just creating an SkNoDrawCanvas
  // with the recording_bounds_ makes a canvas of size (width x height) instead
  // which is incorrect.  SkRecorder cheats with private resetForNextCanvas.
  canvas_->clipRect(recording_bounds_, SkClipOp::kIntersect, false);
  return &*canvas_;
}

bool RecordPaintCanvas::InitializedWithRecordingBounds() const {
  // If the RecordPaintCanvas is initialized with an empty bounds then
  // the various clip related functions are not valid and should not
  // be called.
  return !recording_bounds_.isEmpty();
}

}  // namespace cc
