Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 90b91d98 authored by Matt Sarett's avatar Matt Sarett Committed by gitbuildkicker
Browse files

Add SkiaCanvas::captureCanvasState()

Test: Verified bug is fixed.  Wrote unit test.

Bug: 37268771

Change-Id: I9deb7db353cd2129ad245e7f65419670463bb717
(cherry picked from commit 44dc2708)
parent ed46c52c
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include "hwui/MinikinUtils.h"
#include "pipeline/skia/AnimatedDrawables.h"

#include <SkCanvasStateUtils.h>
#include <SkColorSpaceXformCanvas.h>
#include <SkDrawable.h>
#include <SkDeque.h>
@@ -410,6 +411,30 @@ void SkiaCanvas::setDrawFilter(SkDrawFilter* drawFilter) {
    mCanvas->setDrawFilter(drawFilter);
}

// ----------------------------------------------------------------------------
// Canvas state operations: Capture
// ----------------------------------------------------------------------------

SkCanvasState* SkiaCanvas::captureCanvasState() const {
    SkCanvas* canvas = mCanvas;
    if (mCanvasOwned) {
        // Important to use the underlying SkCanvas, not the wrapper.
        canvas = mCanvasOwned.get();
    }

    // Workarounds for http://crbug.com/271096: SW draw only supports
    // translate & scale transforms, and a simple rectangular clip.
    // (This also avoids significant wasted time in calling
    // SkCanvasStateUtils::CaptureCanvasState when the clip is complex).
    if (!canvas->isClipRect() ||
        (canvas->getTotalMatrix().getType() &
                  ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask))) {
      return nullptr;
    }

    return SkCanvasStateUtils::CaptureCanvasState(canvas);
}

// ----------------------------------------------------------------------------
// Canvas draw operations
// ----------------------------------------------------------------------------
+2 −0
Original line number Diff line number Diff line
@@ -102,6 +102,8 @@ public:
    virtual SkDrawFilter* getDrawFilter() override;
    virtual void setDrawFilter(SkDrawFilter* drawFilter) override;

    virtual SkCanvasState* captureCanvasState() const override;

    virtual void drawColor(int color, SkBlendMode mode) override;
    virtual void drawPaint(const SkPaint& paint) override;

+5 −0
Original line number Diff line number Diff line
@@ -27,6 +27,8 @@
#include <SkCanvas.h>
#include <SkMatrix.h>

class SkCanvasState;

namespace minikin {
    class Layout;
}
@@ -200,6 +202,9 @@ public:
    virtual SkDrawFilter* getDrawFilter() = 0;
    virtual void setDrawFilter(SkDrawFilter* drawFilter) = 0;

    // WebView only
    virtual SkCanvasState* captureCanvasState() const { return nullptr; }

// ----------------------------------------------------------------------------
// Canvas draw operations
// ----------------------------------------------------------------------------
+30 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <gtest/gtest.h>
#include <RecordingCanvas.h>
#include <SkBlurDrawLooper.h>
#include <SkCanvasStateUtils.h>
#include <SkPicture.h>
#include <SkPictureRecorder.h>

@@ -128,3 +129,32 @@ TEST(SkiaCanvas, colorSpaceXform) {
    canvas.asSkCanvas()->drawPicture(picture);
    ASSERT_EQ(0xFF0000FF, *skBitmap.getAddr32(0, 0));
}

TEST(SkiaCanvas, captureCanvasState) {
    // Create a software canvas.
    SkImageInfo info = SkImageInfo::Make(1, 1, kN32_SkColorType, kOpaque_SkAlphaType);
    sk_sp<Bitmap> bitmap = Bitmap::allocateHeapBitmap(info);
    SkBitmap skBitmap;
    bitmap->getSkBitmap(&skBitmap);
    skBitmap.eraseColor(0);
    SkiaCanvas canvas(skBitmap);

    // Translate, then capture and verify the CanvasState.
    canvas.translate(1.0f, 1.0f);
    SkCanvasState* state = canvas.captureCanvasState();
    ASSERT_NE(state, nullptr);
    std::unique_ptr<SkCanvas> newCanvas = SkCanvasStateUtils::MakeFromCanvasState(state);
    ASSERT_NE(newCanvas.get(), nullptr);
    newCanvas->translate(-1.0f, -1.0f);
    ASSERT_TRUE(newCanvas->getTotalMatrix().isIdentity());
    SkCanvasStateUtils::ReleaseCanvasState(state);

    // Create a picture canvas.
    SkPictureRecorder recorder;
    SkCanvas* skPicCanvas = recorder.beginRecording(1, 1, NULL, 0);
    SkiaCanvas picCanvas(skPicCanvas, Canvas::XformToSRGB::kDefer);
    state = picCanvas.captureCanvasState();

    // Verify that we cannot get the CanvasState.
    ASSERT_EQ(state, nullptr);
}