/* * Copyright 2012 The Android Open Source Project * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "SkBitmapSource.h" #include "SkDevice.h" #include "SkCanvas.h" #include "SkReadBuffer.h" #include "SkWriteBuffer.h" #include "SkValidationUtils.h" SkBitmapSource::SkBitmapSource(const SkBitmap& bitmap) : INHERITED(0, 0) , 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) {} #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING SkBitmapSource::SkBitmapSource(SkReadBuffer& buffer) : INHERITED(0, buffer) { if (buffer.isVersionLT(SkReadBuffer::kNoMoreBitmapFlatten_Version)) { fBitmap.legacyUnflatten(buffer); } else { buffer.readBitmap(&fBitmap); } buffer.readRect(&fSrcRect); buffer.readRect(&fDstRect); buffer.validate(buffer.isValid() && SkIsValidRect(fSrcRect) && SkIsValidRect(fDstRect)); } #endif SkFlattenable* SkBitmapSource::CreateProc(SkReadBuffer& buffer) { SkRect src, dst; buffer.readRect(&src); buffer.readRect(&dst); SkBitmap bitmap; if (!buffer.readBitmap(&bitmap)) { return NULL; } return SkBitmapSource::Create(bitmap, src, dst); } void SkBitmapSource::flatten(SkWriteBuffer& buffer) const { buffer.writeRect(fSrcRect); buffer.writeRect(fDstRect); buffer.writeBitmap(fBitmap); } bool SkBitmapSource::onFilterImage(Proxy* proxy, const SkBitmap&, const Context& ctx, SkBitmap* result, SkIPoint* offset) const { SkRect bounds, dstRect; fBitmap.getBounds(&bounds); ctx.ctm().mapRect(&dstRect, fDstRect); if (fSrcRect == bounds && dstRect == bounds) { // No regions cropped out or resized; return entire bitmap. *result = fBitmap; offset->fX = offset->fY = 0; return true; } SkIRect dstIRect; dstRect.roundOut(&dstIRect); SkAutoTUnref 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::kHigh_FilterLevel); canvas.drawBitmapRectToRect(fBitmap, &fSrcRect, dstRect, &paint); *result = device.get()->accessBitmap(false); offset->fX = dstIRect.fLeft; offset->fY = dstIRect.fTop; return true; } void SkBitmapSource::computeFastBounds(const SkRect&, SkRect* dst) const { *dst = fDstRect; } bool SkBitmapSource::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRect* dst) const { *dst = src; return true; }