aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar senorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-05-30 20:50:56 +0000
committerGravatar senorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-05-30 20:50:56 +0000
commit97f5fc651956287e78e35934cf62b9e1b45b4f6c (patch)
tree9aed84527f56452f05442457830ac30f0ef2ba6d
parent1fd263edb3bac44c8921bd34590bbc57fb348001 (diff)
Allow SkPictureImageFilter to be serialized when not run cross-process.
Picture serialization is not yet hardened, but it turns out we do need serialization of SkPictureImageFilter for deferred SVG-on-SVG filters, since the SkPaints (and thus the SkImageFilters) are serialized by SkPictureRecord. However, deferred filters are always drawn in the same process, so we can safely serialize them in this case. We do this by turning the compile-time check for SK_ALLOW_PICTUREIMAGEFILTER_SERIALIZATION to a runtime check for isCrossProcess(). The image filter fuzzer sample was also modified to enable fuzzing of basic picture image filters (the code had rotted a bit, being behind an #ifdef that no one sets). BUG=375162 R=sugoi@google.com Review URL: https://codereview.chromium.org/311443003 git-svn-id: http://skia.googlecode.com/svn/trunk@15008 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r--samplecode/SampleFilterFuzz.cpp17
-rw-r--r--src/effects/SkPictureImageFilter.cpp28
-rw-r--r--tests/ImageFilterTest.cpp61
3 files changed, 82 insertions, 24 deletions
diff --git a/samplecode/SampleFilterFuzz.cpp b/samplecode/SampleFilterFuzz.cpp
index 0cba43c266..7f4c2474fc 100644
--- a/samplecode/SampleFilterFuzz.cpp
+++ b/samplecode/SampleFilterFuzz.cpp
@@ -27,6 +27,7 @@
#include "SkOffsetImageFilter.h"
#include "SkPerlinNoiseShader.h"
#include "SkPictureImageFilter.h"
+#include "SkPictureRecorder.h"
#include "SkRandom.h"
#include "SkRectShaderImageFilter.h"
#include "SkTestImageFilters.h"
@@ -206,7 +207,6 @@ static const SkBitmap& make_bitmap() {
return bitmap[R(2)];
}
-#ifdef SK_ALLOW_PICTUREIMAGEFILTER_SERIALIZATION
static void drawSomething(SkCanvas* canvas) {
SkPaint paint;
@@ -228,7 +228,6 @@ static void drawSomething(SkCanvas* canvas) {
paint.setTextSize(SkIntToScalar(kBitmapSize/3));
canvas->drawText("Picture", 7, SkIntToScalar(kBitmapSize/2), SkIntToScalar(kBitmapSize/4), paint);
}
-#endif
static SkImageFilter* make_image_filter(bool canBeNull = true) {
SkImageFilter* filter = 0;
@@ -376,14 +375,12 @@ static SkImageFilter* make_image_filter(bool canBeNull = true) {
break;
case PICTURE:
{
- SkPicture* pict = NULL;
-#ifdef SK_ALLOW_PICTUREIMAGEFILTER_SERIALIZATION
- pict = new SkPicture;
- SkAutoUnref aur(pict);
- drawSomething(pict->beginRecording(kBitmapSize, kBitmapSize));
- pict->endRecording();
-#endif
- filter = SkPictureImageFilter::Create(pict, make_rect());
+ SkRTreeFactory factory;
+ SkPictureRecorder recorder;
+ SkCanvas* recordingCanvas = recorder.beginRecording(kBitmapSize, kBitmapSize, &factory, 0);
+ drawSomething(recordingCanvas);
+ SkAutoTUnref<SkPicture> pict(recorder.endRecording());
+ filter = SkPictureImageFilter::Create(pict.get(), make_rect());
}
break;
default:
diff --git a/src/effects/SkPictureImageFilter.cpp b/src/effects/SkPictureImageFilter.cpp
index a2f558f202..af9466f977 100644
--- a/src/effects/SkPictureImageFilter.cpp
+++ b/src/effects/SkPictureImageFilter.cpp
@@ -34,27 +34,27 @@ SkPictureImageFilter::~SkPictureImageFilter() {
SkPictureImageFilter::SkPictureImageFilter(SkReadBuffer& buffer)
: INHERITED(0, buffer),
fPicture(NULL) {
-#ifdef SK_ALLOW_PICTUREIMAGEFILTER_SERIALIZATION
- if (buffer.readBool()) {
- fPicture = SkPicture::CreateFromBuffer(buffer);
+ if (!buffer.isCrossProcess()) {
+ if (buffer.readBool()) {
+ fPicture = SkPicture::CreateFromBuffer(buffer);
+ }
+ } else {
+ buffer.validate(!buffer.readBool());
}
-#else
- buffer.readBool();
-#endif
buffer.readRect(&fCropRect);
}
void SkPictureImageFilter::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
-#ifdef SK_ALLOW_PICTUREIMAGEFILTER_SERIALIZATION
- bool hasPicture = (fPicture != NULL);
- buffer.writeBool(hasPicture);
- if (hasPicture) {
- fPicture->flatten(buffer);
+ if (!buffer.isCrossProcess()) {
+ bool hasPicture = (fPicture != NULL);
+ buffer.writeBool(hasPicture);
+ if (hasPicture) {
+ fPicture->flatten(buffer);
+ }
+ } else {
+ buffer.writeBool(false);
}
-#else
- buffer.writeBool(false);
-#endif
buffer.writeRect(fCropRect);
}
diff --git a/tests/ImageFilterTest.cpp b/tests/ImageFilterTest.cpp
index 35585ac5f0..0c4d0766b5 100644
--- a/tests/ImageFilterTest.cpp
+++ b/tests/ImageFilterTest.cpp
@@ -17,6 +17,7 @@
#include "SkDisplacementMapEffect.h"
#include "SkDropShadowImageFilter.h"
#include "SkFlattenableBuffers.h"
+#include "SkFlattenableSerialization.h"
#include "SkGradientShader.h"
#include "SkLightingImageFilter.h"
#include "SkMatrixConvolutionImageFilter.h"
@@ -493,6 +494,66 @@ DEF_TEST(ImageFilterMatrixTest, reporter) {
canvas.drawPicture(*picture);
}
+DEF_TEST(ImageFilterPictureImageFilterTest, reporter) {
+
+ SkRTreeFactory factory;
+ SkPictureRecorder recorder;
+ SkCanvas* recordingCanvas = recorder.beginRecording(1, 1, &factory, 0);
+
+ // Create an SkPicture which simply draws a green 1x1 rectangle.
+ SkPaint greenPaint;
+ greenPaint.setColor(SK_ColorGREEN);
+ recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), greenPaint);
+ SkAutoTUnref<SkPicture> picture(recorder.endRecording());
+
+ // Wrap that SkPicture in an SkPictureImageFilter.
+ SkAutoTUnref<SkImageFilter> imageFilter(
+ SkPictureImageFilter::Create(picture.get()));
+
+ // Check that SkPictureImageFilter successfully serializes its contained
+ // SkPicture when not in cross-process mode.
+ SkPaint paint;
+ paint.setImageFilter(imageFilter.get());
+ SkPictureRecorder outerRecorder;
+ SkCanvas* outerCanvas = outerRecorder.beginRecording(1, 1, &factory, 0);
+ SkPaint redPaintWithFilter;
+ redPaintWithFilter.setColor(SK_ColorRED);
+ redPaintWithFilter.setImageFilter(imageFilter.get());
+ outerCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), redPaintWithFilter);
+ SkAutoTUnref<SkPicture> outerPicture(outerRecorder.endRecording());
+
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(1, 1);
+ SkBitmapDevice device(bitmap);
+ SkCanvas canvas(&device);
+
+ // The result here should be green, since the filter replaces the primitive's red interior.
+ canvas.clear(0x0);
+ canvas.drawPicture(*outerPicture);
+ uint32_t pixel = *bitmap.getAddr32(0, 0);
+ REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
+
+ // Check that, for now, SkPictureImageFilter does not serialize or
+ // deserialize its contained picture when the filter is serialized
+ // cross-process. Do this by "laundering" it through SkValidatingReadBuffer.
+ SkAutoTUnref<SkData> data(SkValidatingSerializeFlattenable(imageFilter.get()));
+ SkAutoTUnref<SkFlattenable> flattenable(SkValidatingDeserializeFlattenable(
+ data->data(), data->size(), SkImageFilter::GetFlattenableType()));
+ SkImageFilter* unflattenedFilter = static_cast<SkImageFilter*>(flattenable.get());
+
+ redPaintWithFilter.setImageFilter(unflattenedFilter);
+ SkPictureRecorder crossProcessRecorder;
+ SkCanvas* crossProcessCanvas = crossProcessRecorder.beginRecording(1, 1, &factory, 0);
+ crossProcessCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), redPaintWithFilter);
+ SkAutoTUnref<SkPicture> crossProcessPicture(crossProcessRecorder.endRecording());
+
+ canvas.clear(0x0);
+ canvas.drawPicture(*crossProcessPicture);
+ pixel = *bitmap.getAddr32(0, 0);
+ // The result here should not be green, since the filter draws nothing.
+ REPORTER_ASSERT(reporter, pixel != SK_ColorGREEN);
+}
+
DEF_TEST(ImageFilterEmptySaveLayerTest, reporter) {
// Even when there's an empty saveLayer()/restore(), ensure that an image