1 /* 2 * Copyright 2013 Google Inc. 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 "SkTileImageFilter.h" 9 #include "SkBitmap.h" 10 #include "SkCanvas.h" 11 #include "SkDevice.h" 12 #include "SkFlattenableBuffers.h" 13 #include "SkMatrix.h" 14 #include "SkPaint.h" 15 #include "SkShader.h" 16 #include "SkValidationUtils.h" 17 18 bool SkTileImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm, 19 SkBitmap* dst, SkIPoint* offset) { 20 SkBitmap source = src; 21 SkImageFilter* input = getInput(0); 22 SkIPoint localOffset = SkIPoint::Make(0, 0); 23 if (input && !input->filterImage(proxy, src, ctm, &source, &localOffset)) { 24 return false; 25 } 26 27 SkRect dstRect; 28 ctm.mapRect(&dstRect, fDstRect); 29 int w = SkScalarCeilToInt(dstRect.width()); 30 int h = SkScalarCeilToInt(dstRect.height()); 31 if (!fSrcRect.width() || !fSrcRect.height() || !w || !h) { 32 return false; 33 } 34 35 SkRect srcRect; 36 ctm.mapRect(&srcRect, fSrcRect); 37 SkIRect srcIRect; 38 srcRect.roundOut(&srcIRect); 39 SkBitmap subset; 40 SkIRect bounds; 41 source.getBounds(&bounds); 42 if (!srcIRect.intersect(bounds)) { 43 return true; 44 } else if (!source.extractSubset(&subset, srcIRect)) { 45 return false; 46 } 47 48 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(w, h)); 49 if (NULL == device.get()) { 50 return false; 51 } 52 SkCanvas canvas(device); 53 SkPaint paint; 54 paint.setXfermodeMode(SkXfermode::kSrc_Mode); 55 56 SkAutoTUnref<SkShader> shader(SkShader::CreateBitmapShader(subset, 57 SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode)); 58 paint.setShader(shader); 59 dstRect.offset(SkIntToScalar(localOffset.fX), SkIntToScalar(localOffset.fY)); 60 canvas.drawRect(dstRect, paint); 61 *dst = device->accessBitmap(false); 62 return true; 63 } 64 65 SkTileImageFilter::SkTileImageFilter(SkFlattenableReadBuffer& buffer) 66 : INHERITED(1, buffer) { 67 buffer.readRect(&fSrcRect); 68 buffer.readRect(&fDstRect); 69 buffer.validate(buffer.isValid() && SkIsValidRect(fSrcRect) && SkIsValidRect(fDstRect)); 70 } 71 72 void SkTileImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { 73 this->INHERITED::flatten(buffer); 74 buffer.writeRect(fSrcRect); 75 buffer.writeRect(fDstRect); 76 } 77