aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar senorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-12-05 22:41:53 +0000
committerGravatar senorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-12-05 22:41:53 +0000
commitaf35920e6d37035c052864bcf254a267a529dbd2 (patch)
treeb06d8fba6544d8b43686f791d818ec5a2bccdf33 /src
parentc94a9911b11783321cf9edd13bb69ea86aa4f929 (diff)
Implement srcRect and dstRect functionality in SkBitmapSource. This is required for the "preserveAspectRatio" options of SVG's feImage. Covered by new GM "bitmapsource".
Note: I initially implemented this as a fully-generic SkResizeImageFilter, but then I realized that the dstRect should always be transformed by the filter matrix, but that the srcRect should not (since it's specified relative to the dimensions of the original bitmap). Since this would be confusing for someone attempting to use this as a generic resizing filter, I decided to build the functionality into SkBitmapSource instead. BUG= R=reed@google.com Review URL: https://codereview.chromium.org/106933002 git-svn-id: http://skia.googlecode.com/svn/trunk@12522 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r--src/effects/SkBitmapSource.cpp53
1 files changed, 50 insertions, 3 deletions
diff --git a/src/effects/SkBitmapSource.cpp b/src/effects/SkBitmapSource.cpp
index 72f51f8423..5e19744a26 100644
--- a/src/effects/SkBitmapSource.cpp
+++ b/src/effects/SkBitmapSource.cpp
@@ -6,24 +6,71 @@
*/
#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) {
+ *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;
}