| /* | |
| * 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/SkPicture.h" | |
| #include "include/core/SkRasterHandleAllocator.h" | |
| #include "include/core/SkRefCnt.h" | |
| #include "include/private/base/SkAssert.h" | |
| #include "include/utils/SkNWayCanvas.h" | |
| #include "src/capture/SkCaptureManager.h" | |
| #include "src/core/SkCanvasPriv.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()); | |
| } | |
| void SkCaptureCanvas::onSurfaceDelete() { | |
| // TODO (b/412351769): signal to the capture manager that this canvas's surface has been deleted | |
| } | |
| //////////////////// 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); | |
| } | |
| 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); | |
| } | |
| 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); | |
| } | |
| 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); | |
| } | |
| 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); | |
| } |