diff options
-rw-r--r-- | expectations/gm/ignored-tests.txt | 31 | ||||
-rw-r--r-- | include/core/SkDevice.h | 5 | ||||
-rw-r--r-- | include/pdf/SkPDFDevice.h | 4 | ||||
-rw-r--r-- | src/core/SkCanvas.cpp | 2 | ||||
-rw-r--r-- | src/core/SkDevice.cpp | 4 | ||||
-rw-r--r-- | src/core/SkDeviceImageFilterProxy.h | 2 | ||||
-rw-r--r-- | src/pdf/SkPDFDevice.cpp | 10 | ||||
-rw-r--r-- | tests/PDFPrimitivesTest.cpp | 52 |
8 files changed, 103 insertions, 7 deletions
diff --git a/expectations/gm/ignored-tests.txt b/expectations/gm/ignored-tests.txt index 86cc83ce21..5f16953307 100644 --- a/expectations/gm/ignored-tests.txt +++ b/expectations/gm/ignored-tests.txt @@ -57,3 +57,34 @@ imagefiltersbase # jvanverth - adding color emoji to df text dftext + +# senorblanco https://codereview.chromium.org/644323006/ +# PDF backend now supports image filters +bitmapsource +colorfilterimagefilter +displacement +dropshadowimagefilter +imagealphathreshold +imageblur +imageblur2 +imageblur_large +imageblurtiled +imagefiltersbase +imagefiltersclipped +imagefilterscropexpand +imagefilterscropped +imagefiltersgraph +imagefiltersscaled +imagemagnifier +imageresizetiled +lighting +matrixconvolution +matriximagefilter +morphology +offsetimagefilter +pictureimagefilter +resizeimagefilter +spritebitmap +testimagefilters +tileimagefilter +xfermodeimagefilter diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h index fb3c206e9e..5984681622 100644 --- a/include/core/SkDevice.h +++ b/include/core/SkDevice.h @@ -121,7 +121,8 @@ public: protected: enum Usage { kGeneral_Usage, - kSaveLayer_Usage // <! internal use only + kSaveLayer_Usage, // <! internal use only + kImageFilter_Usage // <! internal use only }; struct TextFlags { @@ -368,6 +369,8 @@ private: void setOrigin(int x, int y) { fOrigin.set(x, y); } // just called by SkCanvas for saveLayer SkBaseDevice* createCompatibleDeviceForSaveLayer(const SkImageInfo&); + // just called by SkCanvas for imagefilter + SkBaseDevice* createCompatibleDeviceForImageFilter(const SkImageInfo&); virtual SkBaseDevice* onCreateDevice(const SkImageInfo&, Usage) { return NULL; diff --git a/include/pdf/SkPDFDevice.h b/include/pdf/SkPDFDevice.h index 0ada5312ae..f6f782b99a 100644 --- a/include/pdf/SkPDFDevice.h +++ b/include/pdf/SkPDFDevice.h @@ -213,10 +213,6 @@ protected: return fLegacyBitmap; } - virtual bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE { - return false; - } - virtual SkSurface* newSurface(const SkImageInfo&, const SkSurfaceProps&) SK_OVERRIDE; private: diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index 709cb4c0be..2f7fcf4d4b 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -933,7 +933,7 @@ int SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, Save if (paint && paint->getImageFilter()) { device = this->getDevice(); if (device) { - device = device->createCompatibleDevice(info); + device = device->createCompatibleDeviceForImageFilter(info); } } else { device = this->createLayerDevice(info); diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp index 0623f9909e..b912e6aef0 100644 --- a/src/core/SkDevice.cpp +++ b/src/core/SkDevice.cpp @@ -36,6 +36,10 @@ SkBaseDevice* SkBaseDevice::createCompatibleDeviceForSaveLayer(const SkImageInfo return this->onCreateDevice(info, kSaveLayer_Usage); } +SkBaseDevice* SkBaseDevice::createCompatibleDeviceForImageFilter(const SkImageInfo& info) { + return this->onCreateDevice(info, kImageFilter_Usage); +} + SkMetaData& SkBaseDevice::getMetaData() { // metadata users are rare, so we lazily allocate it. If that changes we // can decide to just make it a field in the device (rather than a ptr) diff --git a/src/core/SkDeviceImageFilterProxy.h b/src/core/SkDeviceImageFilterProxy.h index 5ee563484e..0b83b1a81e 100644 --- a/src/core/SkDeviceImageFilterProxy.h +++ b/src/core/SkDeviceImageFilterProxy.h @@ -15,7 +15,7 @@ public: SkDeviceImageFilterProxy(SkBaseDevice* device) : fDevice(device) {} virtual SkBaseDevice* createDevice(int w, int h) SK_OVERRIDE { - return fDevice->createCompatibleDevice(SkImageInfo::MakeN32Premul(w, h)); + return fDevice->createCompatibleDeviceForImageFilter(SkImageInfo::MakeN32Premul(w, h)); } virtual bool canHandleImageFilter(const SkImageFilter* filter) SK_OVERRIDE { return fDevice->canHandleImageFilter(filter); diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp index 736c50b9a6..8509de86fc 100644 --- a/src/pdf/SkPDFDevice.cpp +++ b/src/pdf/SkPDFDevice.cpp @@ -8,6 +8,7 @@ #include "SkPDFDevice.h" #include "SkAnnotation.h" +#include "SkBitmapDevice.h" #include "SkColor.h" #include "SkClipStack.h" #include "SkData.h" @@ -567,6 +568,15 @@ void GraphicStackState::updateDrawingState(const GraphicStateEntry& state) { } SkBaseDevice* SkPDFDevice::onCreateDevice(const SkImageInfo& info, Usage usage) { + // PDF does not support image filters, so render them on CPU. + // Note that this rendering is done at "screen" resolution (100dpi), not + // printer resolution. + // FIXME: It may be possible to express some filters natively using PDF + // to improve quality and file size (http://skbug.com/3043) + if (kImageFilter_Usage == usage) { + return SkBitmapDevice::Create(info); + } + SkMatrix initialTransform; initialTransform.reset(); SkISize size = SkISize::Make(info.width(), info.height()); diff --git a/tests/PDFPrimitivesTest.cpp b/tests/PDFPrimitivesTest.cpp index b1d482ffa2..05677cd1ab 100644 --- a/tests/PDFPrimitivesTest.cpp +++ b/tests/PDFPrimitivesTest.cpp @@ -15,6 +15,7 @@ #include "SkPDFDevice.h" #include "SkPDFStream.h" #include "SkPDFTypes.h" +#include "SkReadBuffer.h" #include "SkScalar.h" #include "SkStream.h" #include "SkTypes.h" @@ -428,3 +429,54 @@ DEF_TEST(PDFPrimitives, reporter) { TestImages(reporter); } + +namespace { + +class DummyImageFilter : public SkImageFilter { +public: + DummyImageFilter(bool visited = false) : SkImageFilter(0, NULL), fVisited(visited) {} + virtual ~DummyImageFilter() SK_OVERRIDE {} + virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&, + SkBitmap* result, SkIPoint* offset) const { + fVisited = true; + offset->fX = offset->fY = 0; + *result = src; + return true; + } + SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(DummyImageFilter) +#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING + explicit DummyImageFilter(SkReadBuffer& buffer) : SkImageFilter(0, NULL) { + fVisited = buffer.readBool(); + } +#endif + bool visited() const { return fVisited; } + +private: + mutable bool fVisited; +}; + +SkFlattenable* DummyImageFilter::CreateProc(SkReadBuffer& buffer) { + SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 0); + bool visited = buffer.readBool(); + return SkNEW_ARGS(DummyImageFilter, (visited)); +} + +}; + +// Check that PDF rendering of image filters successfully falls back to +// CPU rasterization. +DEF_TEST(PDFImageFilter, reporter) { + SkISize pageSize = SkISize::Make(100, 100); + SkAutoTUnref<SkPDFDevice> device(new SkPDFDevice(pageSize, pageSize, SkMatrix::I())); + SkCanvas canvas(device.get()); + SkAutoTUnref<DummyImageFilter> filter(new DummyImageFilter()); + + // Filter just created; should be unvisited. + REPORTER_ASSERT(reporter, !filter->visited()); + SkPaint paint; + paint.setImageFilter(filter.get()); + canvas.drawRect(SkRect::MakeWH(100, 100), paint); + + // Filter was used in rendering; should be visited. + REPORTER_ASSERT(reporter, filter->visited()); +} |