Index: src/effects/SkBitmapSource.cpp |
diff --git a/src/effects/SkBitmapSource.cpp b/src/effects/SkBitmapSource.cpp |
index 72f51f8423a0d06ec21ff4d104dec82bd7a579a5..ef5ea8692568b3c818d977aa885b5517aa53aea3 100644 |
--- a/src/effects/SkBitmapSource.cpp |
+++ b/src/effects/SkBitmapSource.cpp |
@@ -6,24 +6,74 @@ |
*/ |
#include "SkBitmapSource.h" |
+#include "SkDevice.h" |
+#include "SkCanvas.h" |
+#include "SkFlattenableBuffers.h" |
+#include "SkValidationUtils.h" |
SkBitmapSource::SkBitmapSource(const SkBitmap& bitmap) |
: INHERITED(0, 0), |
- fBitmap(bitmap) { |
+ fBitmap(bitmap), |
+ fSrcRect(SkRect::MakeWH(SkIntToScalar(bitmap.width()), |
+ SkIntToScalar(bitmap.height()))), |
+ fDstRect(fSrcRect) { |
+} |
+ |
+SkBitmapSource::SkBitmapSource(const SkBitmap& bitmap, const SkRect& srcRect, const SkRect& dstRect) |
+ : INHERITED(0, 0), |
+ fBitmap(bitmap), |
+ fSrcRect(srcRect), |
+ fDstRect(dstRect) { |
} |
SkBitmapSource::SkBitmapSource(SkFlattenableReadBuffer& buffer) |
: INHERITED(0, buffer) { |
fBitmap.unflatten(buffer); |
+ buffer.readRect(&fSrcRect); |
+ buffer.readRect(&fDstRect); |
+ buffer.validate(SkIsValidRect(fSrcRect) && SkIsValidRect(fDstRect)); |
} |
void SkBitmapSource::flatten(SkFlattenableWriteBuffer& buffer) const { |
this->INHERITED::flatten(buffer); |
fBitmap.flatten(buffer); |
+ buffer.writeRect(fSrcRect); |
+ buffer.writeRect(fDstRect); |
} |
-bool SkBitmapSource::onFilterImage(Proxy*, const SkBitmap&, const SkMatrix&, |
+bool SkBitmapSource::onFilterImage(Proxy* proxy, const SkBitmap&, const SkMatrix& matrix, |
SkBitmap* result, SkIPoint* offset) { |
- *result = fBitmap; |
+ SkRect bounds, dstRect; |
+ fBitmap.getBounds(&bounds); |
+ matrix.mapRect(&dstRect, fDstRect); |
+ if (fSrcRect == bounds && dstRect == bounds) { |
+ // No regions cropped out or resized; return entire bitmap. |
+ *result = fBitmap; |
+ return true; |
+ } |
+ SkIRect dstIRect; |
+ dstRect.roundOut(&dstIRect); |
+ |
+ SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(dstIRect.width(), dstIRect.height())); |
+ if (NULL == device.get()) { |
+ return false; |
+ } |
+ |
+ SkCanvas canvas(device.get()); |
+ SkPaint paint; |
+ |
+ // Subtract off the integer component of the translation (will be applied in loc, below). |
+ dstRect.offset(-SkIntToScalar(dstIRect.fLeft), -SkIntToScalar(dstIRect.fTop)); |
+ paint.setXfermodeMode(SkXfermode::kSrc_Mode); |
+ // FIXME: this probably shouldn't be necessary, but drawBitmapRectToRect asserts |
+ // None filtering when it's translate-only |
+ paint.setFilterLevel( |
+ fSrcRect.width() == dstRect.width() && fSrcRect.height() == dstRect.height() ? |
+ SkPaint::kNone_FilterLevel : SkPaint::kMedium_FilterLevel); |
+ canvas.drawBitmapRectToRect(fBitmap, &fSrcRect, dstRect, &paint); |
+ |
+ *result = device.get()->accessBitmap(false); |
+ offset->fX += dstIRect.fLeft; |
+ offset->fY += dstIRect.fTop; |
return true; |
} |