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

Commit 1ef744a3 authored by Doris Liu's avatar Doris Liu Committed by android-build-merger
Browse files

Fix SkShader leak for Gradient VectorDrawable and test am: fc9cf723

am: c47199bb

Change-Id: I261f8f3708f526c15ae93c51d24bdaee054354f6
parents aef552bc c47199bb
Loading
Loading
Loading
Loading
+6 −2
Original line number Original line Diff line number Diff line
@@ -202,7 +202,9 @@ void FullPath::drawPath(SkCanvas* outCanvas, SkPath& renderPath, float strokeSca
    if (properties.getFillGradient() != nullptr) {
    if (properties.getFillGradient() != nullptr) {
        paint.setColor(applyAlpha(SK_ColorBLACK, properties.getFillAlpha()));
        paint.setColor(applyAlpha(SK_ColorBLACK, properties.getFillAlpha()));
        SkShader* newShader = properties.getFillGradient()->newWithLocalMatrix(matrix);
        SkShader* newShader = properties.getFillGradient()->newWithLocalMatrix(matrix);
        paint.setShader(newShader);
        // newWithLocalMatrix(...) creates a new SkShader and returns a bare pointer. We need to
        // remove the extra ref so that the ref count is correctly managed.
        paint.setShader(newShader)->unref();
        needsFill = true;
        needsFill = true;
    } else if (properties.getFillColor() != SK_ColorTRANSPARENT) {
    } else if (properties.getFillColor() != SK_ColorTRANSPARENT) {
        paint.setColor(applyAlpha(properties.getFillColor(), properties.getFillAlpha()));
        paint.setColor(applyAlpha(properties.getFillColor(), properties.getFillAlpha()));
@@ -222,7 +224,9 @@ void FullPath::drawPath(SkCanvas* outCanvas, SkPath& renderPath, float strokeSca
    if (properties.getStrokeGradient() != nullptr) {
    if (properties.getStrokeGradient() != nullptr) {
        paint.setColor(applyAlpha(SK_ColorBLACK, properties.getStrokeAlpha()));
        paint.setColor(applyAlpha(SK_ColorBLACK, properties.getStrokeAlpha()));
        SkShader* newShader = properties.getStrokeGradient()->newWithLocalMatrix(matrix);
        SkShader* newShader = properties.getStrokeGradient()->newWithLocalMatrix(matrix);
        paint.setShader(newShader);
        // newWithLocalMatrix(...) creates a new SkShader and returns a bare pointer. We need to
        // remove the extra ref so that the ref count is correctly managed.
        paint.setShader(newShader)->unref();
        needsStroke = true;
        needsStroke = true;
    } else if (properties.getStrokeColor() != SK_ColorTRANSPARENT) {
    } else if (properties.getStrokeColor() != SK_ColorTRANSPARENT) {
        paint.setColor(applyAlpha(properties.getStrokeColor(), properties.getStrokeAlpha()));
        paint.setColor(applyAlpha(properties.getStrokeColor(), properties.getStrokeAlpha()));
+44 −0
Original line number Original line Diff line number Diff line
@@ -426,5 +426,49 @@ TEST(VectorDrawable, groupProperties) {
    EXPECT_EQ(1.0f, properties->getPivotY());
    EXPECT_EQ(1.0f, properties->getPivotY());


}
}

static SkShader* createShader(bool* isDestroyed) {
    class TestShader : public SkShader {
    public:
        TestShader(bool* isDestroyed) : SkShader(), mDestroyed(isDestroyed) {
        }
        ~TestShader() {
            *mDestroyed = true;
        }

        Factory getFactory() const override { return nullptr; }
    private:
        bool* mDestroyed;
    };
    return new TestShader(isDestroyed);
}

TEST(VectorDrawable, drawPathWithoutIncrementingShaderRefCount) {
    VectorDrawable::FullPath path("m1 1", 4);
    SkBitmap bitmap;
    SkImageInfo info = SkImageInfo::Make(5, 5, kN32_SkColorType, kPremul_SkAlphaType);
    bitmap.setInfo(info);
    bitmap.allocPixels(info);
    SkCanvas canvas(bitmap);

    bool shaderIsDestroyed = false;

    // Initial ref count is 1
    SkShader* shader = createShader(&shaderIsDestroyed);

    // Setting the fill gradient increments the ref count of the shader by 1
    path.mutateStagingProperties()->setFillGradient(shader);
    path.draw(&canvas, SkMatrix::I(), 1.0f, 1.0f, true);
    // Resetting the fill gradient decrements the ref count of the shader by 1
    path.mutateStagingProperties()->setFillGradient(nullptr);

    // Expect ref count to be 1 again, i.e. nothing else to have a ref to the shader now. Unref()
    // again should bring the ref count to zero and consequently trigger detor.
    shader->unref();

    // Verify that detor is called.
    EXPECT_TRUE(shaderIsDestroyed);
}

}; // namespace uirenderer
}; // namespace uirenderer
}; // namespace android
}; // namespace android