1/* 2 * Copyright 2012 The Android Open Source Project 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "SkBitmapSource.h" 9#include "SkDevice.h" 10#include "SkCanvas.h" 11#include "SkReadBuffer.h" 12#include "SkWriteBuffer.h" 13#include "SkValidationUtils.h" 14 15SkBitmapSource::SkBitmapSource(const SkBitmap& bitmap) 16 : INHERITED(0, 0) 17 , fBitmap(bitmap) 18 , fSrcRect(SkRect::MakeWH(SkIntToScalar(bitmap.width()), 19 SkIntToScalar(bitmap.height()))) 20 , fDstRect(fSrcRect) 21{} 22 23SkBitmapSource::SkBitmapSource(const SkBitmap& bitmap, const SkRect& srcRect, const SkRect& dstRect) 24 : INHERITED(0, 0) 25 , fBitmap(bitmap) 26 , fSrcRect(srcRect) 27 , fDstRect(dstRect) {} 28 29#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING 30SkBitmapSource::SkBitmapSource(SkReadBuffer& buffer) : INHERITED(0, buffer) { 31 if (buffer.isVersionLT(SkReadBuffer::kNoMoreBitmapFlatten_Version)) { 32 fBitmap.legacyUnflatten(buffer); 33 } else { 34 buffer.readBitmap(&fBitmap); 35 } 36 buffer.readRect(&fSrcRect); 37 buffer.readRect(&fDstRect); 38 buffer.validate(buffer.isValid() && SkIsValidRect(fSrcRect) && SkIsValidRect(fDstRect)); 39} 40#endif 41 42SkFlattenable* SkBitmapSource::CreateProc(SkReadBuffer& buffer) { 43 SkRect src, dst; 44 buffer.readRect(&src); 45 buffer.readRect(&dst); 46 SkBitmap bitmap; 47 if (!buffer.readBitmap(&bitmap)) { 48 return NULL; 49 } 50 return SkBitmapSource::Create(bitmap, src, dst); 51} 52 53void SkBitmapSource::flatten(SkWriteBuffer& buffer) const { 54 buffer.writeRect(fSrcRect); 55 buffer.writeRect(fDstRect); 56 buffer.writeBitmap(fBitmap); 57} 58 59bool SkBitmapSource::onFilterImage(Proxy* proxy, const SkBitmap&, const Context& ctx, 60 SkBitmap* result, SkIPoint* offset) const { 61 SkRect bounds, dstRect; 62 fBitmap.getBounds(&bounds); 63 ctx.ctm().mapRect(&dstRect, fDstRect); 64 if (fSrcRect == bounds && dstRect == bounds) { 65 // No regions cropped out or resized; return entire bitmap. 66 *result = fBitmap; 67 offset->fX = offset->fY = 0; 68 return true; 69 } 70 SkIRect dstIRect; 71 dstRect.roundOut(&dstIRect); 72 73 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(dstIRect.width(), dstIRect.height())); 74 if (NULL == device.get()) { 75 return false; 76 } 77 78 SkCanvas canvas(device.get()); 79 SkPaint paint; 80 81 // Subtract off the integer component of the translation (will be applied in loc, below). 82 dstRect.offset(-SkIntToScalar(dstIRect.fLeft), -SkIntToScalar(dstIRect.fTop)); 83 paint.setXfermodeMode(SkXfermode::kSrc_Mode); 84 // FIXME: this probably shouldn't be necessary, but drawBitmapRectToRect asserts 85 // None filtering when it's translate-only 86 paint.setFilterLevel( 87 fSrcRect.width() == dstRect.width() && fSrcRect.height() == dstRect.height() ? 88 SkPaint::kNone_FilterLevel : SkPaint::kHigh_FilterLevel); 89 canvas.drawBitmapRectToRect(fBitmap, &fSrcRect, dstRect, &paint); 90 91 *result = device.get()->accessBitmap(false); 92 offset->fX = dstIRect.fLeft; 93 offset->fY = dstIRect.fTop; 94 return true; 95} 96 97void SkBitmapSource::computeFastBounds(const SkRect&, SkRect* dst) const { 98 *dst = fDstRect; 99} 100 101bool SkBitmapSource::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, 102 SkIRect* dst) const { 103 *dst = src; 104 return true; 105} 106