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 15 SkBitmapSource::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 , fFilterQuality(kHigh_SkFilterQuality) { 22 } 23 24 SkBitmapSource::SkBitmapSource(const SkBitmap& bitmap, 25 const SkRect& srcRect, const SkRect& dstRect, 26 SkFilterQuality filterQuality) 27 : INHERITED(0, 0) 28 , fBitmap(bitmap) 29 , fSrcRect(srcRect) 30 , fDstRect(dstRect) 31 , fFilterQuality(filterQuality) { 32 } 33 34 SkFlattenable* SkBitmapSource::CreateProc(SkReadBuffer& buffer) { 35 SkFilterQuality filterQuality; 36 if (buffer.isVersionLT(SkReadBuffer::kBitmapSourceFilterQuality_Version)) { 37 filterQuality = kHigh_SkFilterQuality; 38 } else { 39 filterQuality = (SkFilterQuality)buffer.readInt(); 40 } 41 SkRect src, dst; 42 buffer.readRect(&src); 43 buffer.readRect(&dst); 44 SkBitmap bitmap; 45 if (!buffer.readBitmap(&bitmap)) { 46 return NULL; 47 } 48 return SkBitmapSource::Create(bitmap, src, dst, filterQuality); 49 } 50 51 void SkBitmapSource::flatten(SkWriteBuffer& buffer) const { 52 buffer.writeInt(fFilterQuality); 53 buffer.writeRect(fSrcRect); 54 buffer.writeRect(fDstRect); 55 buffer.writeBitmap(fBitmap); 56 } 57 58 bool SkBitmapSource::onFilterImage(Proxy* proxy, const SkBitmap&, const Context& ctx, 59 SkBitmap* result, SkIPoint* offset) const { 60 SkRect bounds, dstRect; 61 fBitmap.getBounds(&bounds); 62 ctx.ctm().mapRect(&dstRect, fDstRect); 63 if (fSrcRect == bounds && dstRect == bounds) { 64 // No regions cropped out or resized; return entire bitmap. 65 *result = fBitmap; 66 offset->fX = offset->fY = 0; 67 return true; 68 } 69 70 const SkIRect dstIRect = dstRect.roundOut(); 71 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(dstIRect.width(), dstIRect.height())); 72 if (NULL == device.get()) { 73 return false; 74 } 75 76 SkCanvas canvas(device.get()); 77 SkPaint paint; 78 79 // Subtract off the integer component of the translation (will be applied in loc, below). 80 dstRect.offset(-SkIntToScalar(dstIRect.fLeft), -SkIntToScalar(dstIRect.fTop)); 81 paint.setXfermodeMode(SkXfermode::kSrc_Mode); 82 // FIXME: this probably shouldn't be necessary, but drawBitmapRectToRect asserts 83 // None filtering when it's translate-only 84 paint.setFilterQuality( 85 fSrcRect.width() == dstRect.width() && fSrcRect.height() == dstRect.height() ? 86 kNone_SkFilterQuality : fFilterQuality); 87 canvas.drawBitmapRectToRect(fBitmap, &fSrcRect, dstRect, &paint); 88 89 *result = device.get()->accessBitmap(false); 90 offset->fX = dstIRect.fLeft; 91 offset->fY = dstIRect.fTop; 92 93 return true; 94 } 95 96 void SkBitmapSource::computeFastBounds(const SkRect&, SkRect* dst) const { 97 *dst = fDstRect; 98 } 99 100 #ifndef SK_IGNORE_TO_STRING 101 void SkBitmapSource::toString(SkString* str) const { 102 str->appendf("SkBitmapSource: ("); 103 str->appendf("src: (%f,%f,%f,%f) dst: (%f,%f,%f,%f) ", 104 fSrcRect.fLeft, fSrcRect.fTop, fSrcRect.fRight, fSrcRect.fBottom, 105 fDstRect.fLeft, fDstRect.fTop, fDstRect.fRight, fDstRect.fBottom); 106 str->appendf("bitmap: (%d,%d)", 107 fBitmap.width(), fBitmap.height()); 108 str->append(")"); 109 } 110 #endif 111