Index: src/effects/SkPictureImageFilter.cpp |
diff --git a/src/effects/SkPictureImageFilter.cpp b/src/effects/SkPictureImageFilter.cpp |
index da5597d69905385bb4fc610cd22aa60735b72724..6c7b2ca9b7f79fcac06e4160be6a93683046927e 100644 |
--- a/src/effects/SkPictureImageFilter.cpp |
+++ b/src/effects/SkPictureImageFilter.cpp |
@@ -13,17 +13,24 @@ |
#include "SkWriteBuffer.h" |
#include "SkValidationUtils.h" |
-SkPictureImageFilter::SkPictureImageFilter(const SkPicture* picture, uint32_t uniqueID) |
+SkPictureImageFilter::SkPictureImageFilter(const SkPicture* picture, uint32_t uniqueID, |
+ PictureResolution pictureResolution, |
+ SkPaint::FilterLevel filterLevel) |
: INHERITED(0, 0, NULL, uniqueID) |
, fPicture(SkSafeRef(picture)) |
- , fCropRect(picture ? picture->cullRect() : SkRect::MakeEmpty()) { |
+ , fCropRect(picture ? picture->cullRect() : SkRect::MakeEmpty()) |
+ , fFilterLevel(filterLevel) |
+ , fPictureResolution(pictureResolution) { |
} |
SkPictureImageFilter::SkPictureImageFilter(const SkPicture* picture, const SkRect& cropRect, |
- uint32_t uniqueID) |
+ uint32_t uniqueID, PictureResolution pictureResolution, |
+ SkPaint::FilterLevel filterLevel) |
: INHERITED(0, 0, NULL, uniqueID) |
, fPicture(SkSafeRef(picture)) |
- , fCropRect(cropRect) { |
+ , fCropRect(cropRect) |
+ , fFilterLevel(filterLevel) |
+ , fPictureResolution(pictureResolution) { |
} |
SkPictureImageFilter::~SkPictureImageFilter() { |
@@ -42,6 +49,13 @@ SkPictureImageFilter::SkPictureImageFilter(SkReadBuffer& buffer) |
buffer.validate(!buffer.readBool()); |
} |
buffer.readRect(&fCropRect); |
+ if (buffer.isVersionLT(SkReadBuffer::kPictureImageFilterResolution_Version)) { |
+ fFilterLevel = SkPaint::kLow_FilterLevel; |
+ fPictureResolution = kDeviceSpace_PictureResolution; |
+ } else { |
+ fFilterLevel = (SkPaint::FilterLevel)buffer.readInt(); |
+ fPictureResolution = (PictureResolution)buffer.readInt(); |
+ } |
} |
#endif |
@@ -57,8 +71,17 @@ SkFlattenable* SkPictureImageFilter::CreateProc(SkReadBuffer& buffer) { |
buffer.validate(!buffer.readBool()); |
} |
buffer.readRect(&cropRect); |
+ SkPaint::FilterLevel filterLevel; |
+ PictureResolution pictureResolution; |
+ if (buffer.isVersionLT(SkReadBuffer::kPictureImageFilterResolution_Version)) { |
+ filterLevel = SkPaint::kLow_FilterLevel; |
+ pictureResolution = kDeviceSpace_PictureResolution; |
+ } else { |
+ filterLevel = (SkPaint::FilterLevel)buffer.readInt(); |
+ pictureResolution = (PictureResolution)buffer.readInt(); |
+ } |
- return Create(picture, cropRect); |
+ return Create(picture, cropRect, 0, pictureResolution, filterLevel); |
} |
void SkPictureImageFilter::flatten(SkWriteBuffer& buffer) const { |
@@ -72,6 +95,8 @@ void SkPictureImageFilter::flatten(SkWriteBuffer& buffer) const { |
buffer.writeBool(false); |
} |
buffer.writeRect(fCropRect); |
+ buffer.writeInt(fFilterLevel); |
+ buffer.writeInt(fPictureResolution); |
} |
bool SkPictureImageFilter::onFilterImage(Proxy* proxy, const SkBitmap&, const Context& ctx, |
@@ -98,17 +123,61 @@ bool SkPictureImageFilter::onFilterImage(Proxy* proxy, const SkBitmap&, const Co |
return false; |
} |
+ if (kLocalSpace_PictureResolution == fPictureResolution && |
+ (ctx.ctm().getType() & ~SkMatrix::kTranslate_Mask)) { |
+ drawPictureAtOriginalResolution(proxy, device.get(), bounds, ctx); |
+ } else { |
+ drawPictureAtNativeResolution(proxy, device.get(), bounds, ctx); |
+ } |
+ |
+ *result = device.get()->accessBitmap(false); |
+ offset->fX = bounds.fLeft; |
+ offset->fY = bounds.fTop; |
+ return true; |
+} |
+ |
+void SkPictureImageFilter::drawPictureAtNativeResolution(Proxy* proxy, SkBaseDevice* device, |
+ const SkIRect& deviceBounds, |
+ const Context& ctx) const { |
// Pass explicit surface props, as the simplified canvas constructor discards device properties. |
// FIXME: switch back to the public constructor (and unfriend) after |
// https://code.google.com/p/skia/issues/detail?id=3142 is fixed. |
- SkCanvas canvas(device.get(), proxy->surfaceProps(), SkCanvas::kDefault_InitFlags); |
+ SkCanvas canvas(device, proxy->surfaceProps(), SkCanvas::kDefault_InitFlags); |
- canvas.translate(-SkIntToScalar(bounds.fLeft), -SkIntToScalar(bounds.fTop)); |
+ canvas.translate(-SkIntToScalar(deviceBounds.fLeft), -SkIntToScalar(deviceBounds.fTop)); |
canvas.concat(ctx.ctm()); |
canvas.drawPicture(fPicture); |
+} |
- *result = device.get()->accessBitmap(false); |
- offset->fX = bounds.fLeft; |
- offset->fY = bounds.fTop; |
- return true; |
+void SkPictureImageFilter::drawPictureAtOriginalResolution(Proxy* proxy, SkBaseDevice* device, |
+ const SkIRect& deviceBounds, |
+ const Context& ctx) const { |
+ SkMatrix inverseCtm; |
+ if (!ctx.ctm().invert(&inverseCtm)) |
+ return; |
+ SkRect localBounds = SkRect::Make(ctx.clipBounds()); |
+ inverseCtm.mapRect(&localBounds); |
+ if (!localBounds.intersect(fCropRect)) |
+ return; |
+ SkIRect localIBounds = localBounds.roundOut(); |
+ SkAutoTUnref<SkBaseDevice> localDevice(proxy->createDevice(localIBounds.width(), localIBounds.height())); |
+ |
+ // Pass explicit surface props, as the simplified canvas constructor discards device properties. |
+ // FIXME: switch back to the public constructor (and unfriend) after |
+ // https://code.google.com/p/skia/issues/detail?id=3142 is fixed. |
+ SkCanvas localCanvas(localDevice, proxy->surfaceProps(), SkCanvas::kDefault_InitFlags); |
+ localCanvas.translate(-SkIntToScalar(localIBounds.fLeft), -SkIntToScalar(localIBounds.fTop)); |
+ localCanvas.drawPicture(fPicture); |
+ |
+ // Pass explicit surface props, as the simplified canvas constructor discards device properties. |
+ // FIXME: switch back to the public constructor (and unfriend) after |
+ // https://code.google.com/p/skia/issues/detail?id=3142 is fixed. |
+ SkCanvas canvas(device, proxy->surfaceProps(), SkCanvas::kDefault_InitFlags); |
+ |
+ canvas.translate(-SkIntToScalar(deviceBounds.fLeft), -SkIntToScalar(deviceBounds.fTop)); |
+ canvas.concat(ctx.ctm()); |
+ SkPaint paint; |
+ paint.setFilterLevel(fFilterLevel); |
+ canvas.drawBitmap(localDevice.get()->accessBitmap(false), SkIntToScalar(localIBounds.fLeft), SkIntToScalar(localIBounds.fTop), &paint); |
+ //canvas.drawPicture(fPicture); |
} |