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, 19 SkScalar sigmaX, SkScalar sigmaY, SkColor color, 20 ShadowMode shadowMode, SkImageFilter* input, 21 const CropRect* cropRect) 22 : INHERITED(1, &input, cropRect) 23 , fDx(dx) 24 , fDy(dy) 25 , fSigmaX(sigmaX) 26 , fSigmaY(sigmaY) 27 , fColor(color) 28 , fShadowMode(shadowMode) 29{ 30} 31 32SkFlattenable* SkDropShadowImageFilter::CreateProc(SkReadBuffer& buffer) { 33 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1); 34 SkScalar dx = buffer.readScalar(); 35 SkScalar dy = buffer.readScalar(); 36 SkScalar sigmaX = buffer.readScalar(); 37 SkScalar sigmaY = buffer.readScalar(); 38 SkColor color = buffer.readColor(); 39 ShadowMode shadowMode = buffer.isVersionLT(SkReadBuffer::kDropShadowMode_Version) ? 40 kDrawShadowAndForeground_ShadowMode : 41 static_cast<ShadowMode>(buffer.readInt()); 42 return Create(dx, dy, sigmaX, sigmaY, color, shadowMode, common.getInput(0), 43 &common.cropRect()); 44} 45 46void SkDropShadowImageFilter::flatten(SkWriteBuffer& buffer) const { 47 this->INHERITED::flatten(buffer); 48 buffer.writeScalar(fDx); 49 buffer.writeScalar(fDy); 50 buffer.writeScalar(fSigmaX); 51 buffer.writeScalar(fSigmaY); 52 buffer.writeColor(fColor); 53 buffer.writeInt(static_cast<int>(fShadowMode)); 54} 55 56bool SkDropShadowImageFilter::onFilterImageDeprecated(Proxy* proxy, const SkBitmap& source, 57 const Context& ctx, 58 SkBitmap* result, SkIPoint* offset) const { 59 SkBitmap src = source; 60 SkIPoint srcOffset = SkIPoint::Make(0, 0); 61 if (!this->filterInputDeprecated(0, proxy, source, ctx, &src, &srcOffset)) 62 return false; 63 64 SkIRect srcBounds = src.bounds(); 65 srcBounds.offset(srcOffset); 66 SkIRect bounds; 67 if (!this->applyCropRect(ctx, srcBounds, &bounds)) { 68 return false; 69 } 70 71 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height())); 72 if (nullptr == device.get()) { 73 return false; 74 } 75 SkCanvas canvas(device.get()); 76 77 SkVector sigma = SkVector::Make(fSigmaX, fSigmaY); 78 ctx.ctm().mapVectors(&sigma, 1); 79 sigma.fX = SkMaxScalar(0, sigma.fX); 80 sigma.fY = SkMaxScalar(0, sigma.fY); 81 SkAutoTUnref<SkImageFilter> blurFilter(SkBlurImageFilter::Create(sigma.fX, sigma.fY)); 82 SkAutoTUnref<SkColorFilter> colorFilter( 83 SkColorFilter::CreateModeFilter(fColor, SkXfermode::kSrcIn_Mode)); 84 SkPaint paint; 85 paint.setImageFilter(blurFilter.get()); 86 paint.setColorFilter(colorFilter.get()); 87 paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); 88 SkVector offsetVec = SkVector::Make(fDx, fDy); 89 ctx.ctm().mapVectors(&offsetVec, 1); 90 canvas.translate(SkIntToScalar(srcOffset.fX - bounds.fLeft), 91 SkIntToScalar(srcOffset.fY - bounds.fTop)); 92 canvas.drawBitmap(src, offsetVec.fX, offsetVec.fY, &paint); 93 if (fShadowMode == kDrawShadowAndForeground_ShadowMode) { 94 canvas.drawBitmap(src, 0, 0); 95 } 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 if (fShadowMode == kDrawShadowAndForeground_ShadowMode) { 114 dst->join(shadowBounds); 115 } else { 116 *dst = shadowBounds; 117 } 118} 119 120void SkDropShadowImageFilter::onFilterNodeBounds(const SkIRect& src, const SkMatrix& ctm, 121 SkIRect* dst, MapDirection direction) const { 122 *dst = src; 123 SkVector offsetVec = SkVector::Make(fDx, fDy); 124 if (kReverse_MapDirection == direction) { 125 offsetVec.negate(); 126 } 127 ctm.mapVectors(&offsetVec, 1); 128 dst->offset(SkScalarCeilToInt(offsetVec.x()), 129 SkScalarCeilToInt(offsetVec.y())); 130 SkVector sigma = SkVector::Make(fSigmaX, fSigmaY); 131 ctm.mapVectors(&sigma, 1); 132 dst->outset(SkScalarCeilToInt(SkScalarMul(sigma.x(), SkIntToScalar(3))), 133 SkScalarCeilToInt(SkScalarMul(sigma.y(), SkIntToScalar(3)))); 134 if (fShadowMode == kDrawShadowAndForeground_ShadowMode) { 135 dst->join(src); 136 } 137} 138 139#ifndef SK_IGNORE_TO_STRING 140void SkDropShadowImageFilter::toString(SkString* str) const { 141 str->appendf("SkDropShadowImageFilter: ("); 142 143 str->appendf("dX: %f ", fDx); 144 str->appendf("dY: %f ", fDy); 145 str->appendf("sigmaX: %f ", fSigmaX); 146 str->appendf("sigmaY: %f ", fSigmaY); 147 148 str->append("Color: "); 149 str->appendHex(fColor); 150 151 static const char* gModeStrings[] = { 152 "kDrawShadowAndForeground", "kDrawShadowOnly" 153 }; 154 155 static_assert(kShadowModeCount == SK_ARRAY_COUNT(gModeStrings), "enum_mismatch"); 156 157 str->appendf(" mode: %s", gModeStrings[fShadowMode]); 158 159 str->append(")"); 160} 161#endif 162