SkDropShadowImageFilter.cpp revision 29089179a66c06ef70da387111af75970f04ed53
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 "SkDropShadowImageFilter.h" 9 10#include "SkBitmap.h" 11#include "SkBlurImageFilter.h" 12#include "SkCanvas.h" 13#include "SkColorMatrixFilter.h" 14#include "SkDevice.h" 15#include "SkReadBuffer.h" 16#include "SkWriteBuffer.h" 17 18SkDropShadowImageFilter::SkDropShadowImageFilter(SkScalar dx, SkScalar dy, SkScalar sigma, SkColor color, SkImageFilter* input) 19 : INHERITED(input) 20 , fDx(dx) 21 , fDy(dy) 22 , fSigmaX(sigma) 23 , fSigmaY(sigma) 24 , fColor(color) 25{ 26} 27 28SkDropShadowImageFilter::SkDropShadowImageFilter(SkScalar dx, SkScalar dy, SkScalar sigmaX, SkScalar sigmaY, SkColor color, SkImageFilter* input, const CropRect* cropRect) 29 : INHERITED(input, cropRect) 30 , fDx(dx) 31 , fDy(dy) 32 , fSigmaX(sigmaX) 33 , fSigmaY(sigmaY) 34 , fColor(color) 35{ 36} 37 38SkDropShadowImageFilter::SkDropShadowImageFilter(SkReadBuffer& buffer) 39 : INHERITED(1, buffer) { 40 fDx = buffer.readScalar(); 41 fDy = buffer.readScalar(); 42 fSigmaX = buffer.readScalar(); 43 fSigmaY = buffer.readScalar(); 44 fColor = buffer.readColor(); 45 buffer.validate(SkScalarIsFinite(fDx) && 46 SkScalarIsFinite(fDy) && 47 SkScalarIsFinite(fSigmaX) && 48 SkScalarIsFinite(fSigmaY)); 49} 50 51void SkDropShadowImageFilter::flatten(SkWriteBuffer& buffer) const 52{ 53 this->INHERITED::flatten(buffer); 54 buffer.writeScalar(fDx); 55 buffer.writeScalar(fDy); 56 buffer.writeScalar(fSigmaX); 57 buffer.writeScalar(fSigmaY); 58 buffer.writeColor(fColor); 59} 60 61bool SkDropShadowImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source, const Context& ctx, SkBitmap* result, SkIPoint* offset) const 62{ 63 SkBitmap src = source; 64 SkIPoint srcOffset = SkIPoint::Make(0, 0); 65 if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctx, &src, &srcOffset)) 66 return false; 67 68 SkIRect bounds; 69 src.getBounds(&bounds); 70 bounds.offset(srcOffset); 71 if (!this->applyCropRect(&bounds, ctx.ctm())) { 72 return false; 73 } 74 75 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height())); 76 if (NULL == device.get()) { 77 return false; 78 } 79 SkCanvas canvas(device.get()); 80 81 SkVector sigma, localSigma = SkVector::Make(fSigmaX, fSigmaY); 82 ctx.ctm().mapVectors(&sigma, &localSigma, 1); 83 sigma.fX = SkMaxScalar(0, sigma.fX); 84 sigma.fY = SkMaxScalar(0, sigma.fY); 85 SkAutoTUnref<SkImageFilter> blurFilter(SkBlurImageFilter::Create(sigma.fX, sigma.fY)); 86 SkAutoTUnref<SkColorFilter> colorFilter(SkColorFilter::CreateModeFilter(fColor, SkXfermode::kSrcIn_Mode)); 87 SkPaint paint; 88 paint.setImageFilter(blurFilter.get()); 89 paint.setColorFilter(colorFilter.get()); 90 paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); 91 SkVector offsetVec, localOffsetVec = SkVector::Make(fDx, fDy); 92 ctx.ctm().mapVectors(&offsetVec, &localOffsetVec, 1); 93 canvas.translate(-SkIntToScalar(bounds.fLeft), -SkIntToScalar(bounds.fTop)); 94 canvas.drawBitmap(src, offsetVec.fX, offsetVec.fY, &paint); 95 canvas.drawBitmap(src, 0, 0); 96 *result = device->accessBitmap(false); 97 offset->fX = bounds.fLeft; 98 offset->fY = bounds.fTop; 99 return true; 100} 101 102void SkDropShadowImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const { 103 if (getInput(0)) { 104 getInput(0)->computeFastBounds(src, dst); 105 } else { 106 *dst = src; 107 } 108 109 SkRect shadowBounds = *dst; 110 shadowBounds.offset(fDx, fDy); 111 shadowBounds.outset(SkScalarMul(fSigmaX, SkIntToScalar(3)), 112 SkScalarMul(fSigmaY, SkIntToScalar(3))); 113 dst->join(shadowBounds); 114} 115 116bool SkDropShadowImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, 117 SkIRect* dst) const { 118 SkIRect bounds = src; 119 if (getInput(0) && !getInput(0)->filterBounds(src, ctm, &bounds)) { 120 return false; 121 } 122 SkVector offsetVec, localOffsetVec = SkVector::Make(fDx, fDy); 123 ctm.mapVectors(&offsetVec, &localOffsetVec, 1); 124 bounds.offset(-SkScalarCeilToInt(offsetVec.x()), 125 -SkScalarCeilToInt(offsetVec.y())); 126 SkVector sigma, localSigma = SkVector::Make(fSigmaX, fSigmaY); 127 ctm.mapVectors(&sigma, &localSigma, 1); 128 bounds.outset(SkScalarCeilToInt(SkScalarMul(sigma.x(), SkIntToScalar(3))), 129 SkScalarCeilToInt(SkScalarMul(sigma.y(), SkIntToScalar(3)))); 130 bounds.join(src); 131 *dst = bounds; 132 return true; 133} 134