michael@0: /* michael@0: * Copyright 2012 The Android Open Source Project michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: #include "SkBitmapSource.h" michael@0: #include "SkDevice.h" michael@0: #include "SkCanvas.h" michael@0: #include "SkReadBuffer.h" michael@0: #include "SkWriteBuffer.h" michael@0: #include "SkValidationUtils.h" michael@0: michael@0: SkBitmapSource::SkBitmapSource(const SkBitmap& bitmap) michael@0: : INHERITED(0, 0), michael@0: fBitmap(bitmap), michael@0: fSrcRect(SkRect::MakeWH(SkIntToScalar(bitmap.width()), michael@0: SkIntToScalar(bitmap.height()))), michael@0: fDstRect(fSrcRect) { michael@0: } michael@0: michael@0: SkBitmapSource::SkBitmapSource(const SkBitmap& bitmap, const SkRect& srcRect, const SkRect& dstRect) michael@0: : INHERITED(0, 0), michael@0: fBitmap(bitmap), michael@0: fSrcRect(srcRect), michael@0: fDstRect(dstRect) { michael@0: } michael@0: michael@0: SkBitmapSource::SkBitmapSource(SkReadBuffer& buffer) michael@0: : INHERITED(0, buffer) { michael@0: fBitmap.unflatten(buffer); michael@0: buffer.readRect(&fSrcRect); michael@0: buffer.readRect(&fDstRect); michael@0: buffer.validate(buffer.isValid() && SkIsValidRect(fSrcRect) && SkIsValidRect(fDstRect)); michael@0: } michael@0: michael@0: void SkBitmapSource::flatten(SkWriteBuffer& buffer) const { michael@0: this->INHERITED::flatten(buffer); michael@0: fBitmap.flatten(buffer); michael@0: buffer.writeRect(fSrcRect); michael@0: buffer.writeRect(fDstRect); michael@0: } michael@0: michael@0: bool SkBitmapSource::onFilterImage(Proxy* proxy, const SkBitmap&, const Context& ctx, michael@0: SkBitmap* result, SkIPoint* offset) const { michael@0: SkRect bounds, dstRect; michael@0: fBitmap.getBounds(&bounds); michael@0: ctx.ctm().mapRect(&dstRect, fDstRect); michael@0: if (fSrcRect == bounds && dstRect == bounds) { michael@0: // No regions cropped out or resized; return entire bitmap. michael@0: *result = fBitmap; michael@0: offset->fX = offset->fY = 0; michael@0: return true; michael@0: } michael@0: SkIRect dstIRect; michael@0: dstRect.roundOut(&dstIRect); michael@0: michael@0: SkAutoTUnref device(proxy->createDevice(dstIRect.width(), dstIRect.height())); michael@0: if (NULL == device.get()) { michael@0: return false; michael@0: } michael@0: michael@0: SkCanvas canvas(device.get()); michael@0: SkPaint paint; michael@0: michael@0: // Subtract off the integer component of the translation (will be applied in loc, below). michael@0: dstRect.offset(-SkIntToScalar(dstIRect.fLeft), -SkIntToScalar(dstIRect.fTop)); michael@0: paint.setXfermodeMode(SkXfermode::kSrc_Mode); michael@0: // FIXME: this probably shouldn't be necessary, but drawBitmapRectToRect asserts michael@0: // None filtering when it's translate-only michael@0: paint.setFilterLevel( michael@0: fSrcRect.width() == dstRect.width() && fSrcRect.height() == dstRect.height() ? michael@0: SkPaint::kNone_FilterLevel : SkPaint::kHigh_FilterLevel); michael@0: canvas.drawBitmapRectToRect(fBitmap, &fSrcRect, dstRect, &paint); michael@0: michael@0: *result = device.get()->accessBitmap(false); michael@0: offset->fX = dstIRect.fLeft; michael@0: offset->fY = dstIRect.fTop; michael@0: return true; michael@0: } michael@0: michael@0: void SkBitmapSource::computeFastBounds(const SkRect&, SkRect* dst) const { michael@0: *dst = fDstRect; michael@0: } michael@0: michael@0: bool SkBitmapSource::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, michael@0: SkIRect* dst) const { michael@0: *dst = src; michael@0: return true; michael@0: }