/*
 * Copyright 2025 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/capture/SkCaptureCanvas.h"

#include "include/core/SkBlender.h"
#include "include/core/SkPicture.h"
#include "include/core/SkRasterHandleAllocator.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSurface.h"
#include "include/private/SkAssert.h"
#include "include/private/SkLog.h"
#include "include/private/chromium/Slug.h"
#include "include/utils/SkNWayCanvas.h"
#include "src/capture/SkCaptureManager.h"
#include "src/core/SkCanvasPriv.h"
#include "src/image/SkImage_Base.h"

SkCaptureCanvas::SkCaptureCanvas(SkCanvas* canvas, SkCaptureManager* manager)
        : SkNWayCanvas(canvas->imageInfo().width(), canvas->imageInfo().height()) {
    fBaseCanvas = canvas;
    fManager = manager;
    this->addCanvas(canvas);
}

SkCaptureCanvas::~SkCaptureCanvas() = default;

void SkCaptureCanvas::pollCapturingStatus() {
    bool shouldPoll = fManager->isCurrentlyCapturing();
    if (fCapturing != shouldPoll) {
        if (shouldPoll) {
            this->attachRecordingCanvas();
        } else {
            this->detachRecordingCanvas();
        }
        fCapturing = shouldPoll;
    }
}

sk_sp<SkPicture> SkCaptureCanvas::snapPicture() {
    if (!fCapturing) {
        return nullptr;
    }
    this->detachRecordingCanvas(); // remove the stale recording canvas before the recorder finishes
    auto skp = fRecorder.finishRecordingAsPicture();
    this->attachRecordingCanvas();
    return skp;
}

void SkCaptureCanvas::attachRecordingCanvas() {
    SkASSERT(this->fList.size() == 1);
    this->addCanvas(fRecorder.beginRecording(fBaseCanvas->imageInfo().width(),
                                              fBaseCanvas->imageInfo().height()));
}

void SkCaptureCanvas::detachRecordingCanvas() {
    SkASSERT(this->fList.size() == 2);
    this->removeCanvas(fRecorder.getRecordingCanvas());
}

sk_sp<SkSurface> SkCaptureCanvas::onNewSurface(const SkImageInfo& info,
                                               const SkSurfaceProps& props) {
    return fBaseCanvas->onNewSurface(info, props);
}

bool SkCaptureCanvas::onPeekPixels(SkPixmap* pixmap) {
    return fBaseCanvas->peekPixels(pixmap);
}

bool SkCaptureCanvas::onAccessTopLayerPixels(SkPixmap* pixmap) {
    return fBaseCanvas->onAccessTopLayerPixels(pixmap);
}

SkImageInfo SkCaptureCanvas::onImageInfo() const {
    return fBaseCanvas->imageInfo();
}

bool SkCaptureCanvas::onGetProps(SkSurfaceProps* props, bool top) const {
    return fBaseCanvas->onGetProps(props, top);
}

sk_sp<sktext::gpu::Slug> SkCaptureCanvas::onConvertGlyphRunListToSlug(
        const sktext::GlyphRunList& glyphRunList, const SkPaint& paint) {
    return fBaseCanvas->onConvertGlyphRunListToSlug(glyphRunList, paint);
}

//////////////////// Function forwarding ///////////////////////

void SkCaptureCanvas::willSave() {
    this->pollCapturingStatus();
    this->SkNWayCanvas::willSave();
}

SkCanvas::SaveLayerStrategy SkCaptureCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
    this->pollCapturingStatus();
    return this->SkNWayCanvas::getSaveLayerStrategy(rec);
}

bool SkCaptureCanvas::onDoSaveBehind(const SkRect* bounds) {
    this->pollCapturingStatus();
    return this->SkNWayCanvas::onDoSaveBehind(bounds);
}

void SkCaptureCanvas::willRestore() {
    this->pollCapturingStatus();
    this->SkNWayCanvas::willRestore();
}

void SkCaptureCanvas::didConcat44(const SkM44& m) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::didConcat44(m);
}

void SkCaptureCanvas::didSetM44(const SkM44& matrix) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::didSetM44(matrix);
}

void SkCaptureCanvas::didTranslate(SkScalar x, SkScalar y) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::didTranslate(x, y);
}

void SkCaptureCanvas::didScale(SkScalar x, SkScalar y) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::didScale(x, y);
}

void SkCaptureCanvas::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onClipRect(rect, op, edgeStyle);
}

void SkCaptureCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onClipRRect(rrect, op, edgeStyle);
}

void SkCaptureCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onClipPath(path, op, edgeStyle);
}

void SkCaptureCanvas::onClipShader(sk_sp<SkShader> sh, SkClipOp op) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onClipShader(sh, op);
}

void SkCaptureCanvas::onClipRegion(const SkRegion& deviceRgn, SkClipOp op) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onClipRegion(deviceRgn, op);
}

void SkCaptureCanvas::onResetClip() {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onResetClip();
}

void SkCaptureCanvas::onDrawPaint(const SkPaint& paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawPaint(paint);
}

void SkCaptureCanvas::onDrawBehind(const SkPaint& paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawBehind(paint);
}

void SkCaptureCanvas::onDrawPoints(PointMode mode,
                                   size_t count,
                                   const SkPoint pts[],
                                   const SkPaint& paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawPoints(mode, count, pts, paint);
}

void SkCaptureCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawRect(rect, paint);
}

void SkCaptureCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawRegion(region, paint);
}

void SkCaptureCanvas::onDrawOval(const SkRect& rect, const SkPaint& paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawOval(rect, paint);
}

void SkCaptureCanvas::onDrawArc(const SkRect& rect,
                                SkScalar startAngle,
                                SkScalar sweepAngle,
                                bool useCenter,
                                const SkPaint& paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawArc(rect, startAngle, sweepAngle, useCenter, paint);
}

void SkCaptureCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawRRect(rrect, paint);
}

void SkCaptureCanvas::onDrawDRRect(const SkRRect& outer,
                                   const SkRRect& inner,
                                   const SkPaint& paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawDRRect(outer, inner, paint);
}

void SkCaptureCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawPath(path, paint);
}

void SkCaptureCanvas::onDrawImage2(const SkImage* image,
                                   SkScalar left,
                                   SkScalar top,
                                   const SkSamplingOptions& sampling,
                                   const SkPaint* paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawImage2(image, left, top, sampling, paint);
    for (const auto& storage : as_IB(image)->getPixelStorages()) {
        if (storage) {
            // TODO (b/412351769): Track image metadata in the capture manager.
            SKIA_LOG_D("SkCaptureCanvas::onDrawImage2: StorageID=%u, ContentID=%u\n",
                     storage->getPixelStorageId(), storage->getContentId());
        }
    }
}

void SkCaptureCanvas::onDrawImageRect2(const SkImage* image,
                                       const SkRect& src,
                                       const SkRect& dst,
                                       const SkSamplingOptions& sampling,
                                       const SkPaint* paint,
                                       SrcRectConstraint constraint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawImageRect2(image, src, dst, sampling, paint, constraint);
    for (const auto& storage : as_IB(image)->getPixelStorages()) {
        if (storage) {
            // TODO (b/412351769): Track image metadata in the capture manager.
            SKIA_LOG_D("SkCaptureCanvas::onDrawImageRect2: StorageID=%u, ContentID=%u\n",
                     storage->getPixelStorageId(), storage->getContentId());
        }
    }
}

void SkCaptureCanvas::onDrawImageLattice2(const SkImage* image,
                                          const Lattice& lattice,
                                          const SkRect& dst,
                                          SkFilterMode filter,
                                          const SkPaint* paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawImageLattice2(image, lattice, dst, filter, paint);
    for (const auto& storage : as_IB(image)->getPixelStorages()) {
        if (storage) {
            // TODO (b/412351769): Track image metadata in the capture manager.
            SKIA_LOG_D("SkCaptureCanvas::onDrawImageLattice2: StorageID=%u, ContentID=%u\n",
                     storage->getPixelStorageId(), storage->getContentId());
        }
    }
}

void SkCaptureCanvas::onDrawAtlas2(const SkImage* image,
                                   const SkRSXform xform[],
                                   const SkRect tex[],
                                   const SkColor colors[],
                                   int count,
                                   SkBlendMode bmode,
                                   const SkSamplingOptions& sampling,
                                   const SkRect* cull,
                                   const SkPaint* paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawAtlas2(image, xform, tex, colors, count, bmode, sampling, cull, paint);
    for (const auto& storage : as_IB(image)->getPixelStorages()) {
        if (storage) {
            // TODO (b/412351769): Track image metadata in the capture manager.
            SKIA_LOG_D("SkCaptureCanvas::onDrawAtlas2: StorageID=%u, ContentID=%u\n",
                     storage->getPixelStorageId(), storage->getContentId());
        }
    }
}

void SkCaptureCanvas::onDrawMesh(const SkMesh& mesh, sk_sp<SkBlender> blender, const SkPaint& paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawMesh(mesh, blender, paint);
}

void SkCaptureCanvas::onDrawGlyphRunList(const sktext::GlyphRunList& list, const SkPaint& paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawGlyphRunList(list, paint);
}

void SkCaptureCanvas::onDrawTextBlob(const SkTextBlob* blob,
                                     SkScalar x,
                                     SkScalar y,
                                     const SkPaint& paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawTextBlob(blob, x, y, paint);
}

void SkCaptureCanvas::onDrawSlug(const sktext::gpu::Slug* slug, const SkPaint& paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawSlug(slug, paint);
}

void SkCaptureCanvas::onDrawPicture(const SkPicture* picture,
                                    const SkMatrix* matrix,
                                    const SkPaint* paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawPicture(picture, matrix, paint);
}

void SkCaptureCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawDrawable(drawable, matrix);
}

void SkCaptureCanvas::onDrawVerticesObject(const SkVertices* vertices,
                                           SkBlendMode bmode,
                                           const SkPaint& paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawVerticesObject(vertices, bmode, paint);
}

void SkCaptureCanvas::onDrawPatch(const SkPoint cubics[12],
                                  const SkColor colors[4],
                                  const SkPoint texCoords[4],
                                  SkBlendMode bmode,
                                  const SkPaint& paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawPatch(cubics, colors, texCoords, bmode, paint);
}

void SkCaptureCanvas::onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawShadowRec(path, rec);
}

void SkCaptureCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* data) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawAnnotation(rect, key, data);
}

void SkCaptureCanvas::onDrawEdgeAAQuad(const SkRect& rect,
                                       const SkPoint clip[4],
                                       QuadAAFlags aa,
                                       const SkColor4f& color,
                                       SkBlendMode mode) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawEdgeAAQuad(rect, clip, aa, color, mode);
}

void SkCaptureCanvas::onDrawEdgeAAImageSet2(const ImageSetEntry set[],
                                            int count,
                                            const SkPoint dstClips[],
                                            const SkMatrix preViewMatrices[],
                                            const SkSamplingOptions& sampling,
                                            const SkPaint* paint,
                                            SrcRectConstraint constraint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawEdgeAAImageSet2(
            set, count, dstClips, preViewMatrices, sampling, paint, constraint);
}
