Merge "Fix SkShader leak for Gradient VectorDrawable and test" into nyc-mr1-dev
This commit is contained in:
@@ -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()));
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user