SkDropShadowImageFilter.cpp revision 410be679754106b5ecbf3b5744b0ef51674cb420
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 "SkFlattenableBuffers.h"
16
17SkDropShadowImageFilter::SkDropShadowImageFilter(SkScalar dx, SkScalar dy, SkScalar sigma, SkColor color, SkImageFilter* input)
18    : INHERITED(input)
19    , fDx(dx)
20    , fDy(dy)
21    , fSigmaX(sigma)
22    , fSigmaY(sigma)
23    , fColor(color)
24{
25}
26
27SkDropShadowImageFilter::SkDropShadowImageFilter(SkScalar dx, SkScalar dy, SkScalar sigmaX, SkScalar sigmaY, SkColor color, SkImageFilter* input, const CropRect* cropRect)
28    : INHERITED(input, cropRect)
29    , fDx(dx)
30    , fDy(dy)
31    , fSigmaX(sigmaX)
32    , fSigmaY(sigmaY)
33    , fColor(color)
34{
35}
36
37SkDropShadowImageFilter::SkDropShadowImageFilter(SkFlattenableReadBuffer& buffer)
38 : INHERITED(1, buffer) {
39    fDx = buffer.readScalar();
40    fDy = buffer.readScalar();
41    fSigmaX = buffer.readScalar();
42    fSigmaY = buffer.readScalar();
43    fColor = buffer.readColor();
44    buffer.validate(SkScalarIsFinite(fDx) &&
45                    SkScalarIsFinite(fDy) &&
46                    SkScalarIsFinite(fSigmaX) &&
47                    SkScalarIsFinite(fSigmaY));
48}
49
50void SkDropShadowImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const
51{
52    this->INHERITED::flatten(buffer);
53    buffer.writeScalar(fDx);
54    buffer.writeScalar(fDy);
55    buffer.writeScalar(fSigmaX);
56    buffer.writeScalar(fSigmaY);
57    buffer.writeColor(fColor);
58}
59
60bool SkDropShadowImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source, const SkMatrix& matrix, SkBitmap* result, SkIPoint* offset)
61{
62    SkBitmap src = source;
63    SkIPoint srcOffset = SkIPoint::Make(0, 0);
64    if (getInput(0) && !getInput(0)->filterImage(proxy, source, matrix, &src, &srcOffset))
65        return false;
66
67    SkIRect bounds;
68    src.getBounds(&bounds);
69    bounds.offset(srcOffset);
70    if (!this->applyCropRect(&bounds, matrix)) {
71        return false;
72    }
73
74    SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
75    if (NULL == device.get()) {
76        return false;
77    }
78    SkCanvas canvas(device.get());
79
80    SkVector sigma, localSigma = SkVector::Make(fSigmaX, fSigmaY);
81    matrix.mapVectors(&sigma, &localSigma, 1);
82    SkAutoTUnref<SkImageFilter> blurFilter(new SkBlurImageFilter(sigma.fX, sigma.fY));
83    SkAutoTUnref<SkColorFilter> colorFilter(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, localOffsetVec = SkVector::Make(fDx, fDy);
89    matrix.mapVectors(&offsetVec, &localOffsetVec, 1);
90    canvas.translate(-SkIntToScalar(bounds.fLeft), -SkIntToScalar(bounds.fTop));
91    canvas.drawBitmap(src, offsetVec.fX, offsetVec.fY, &paint);
92    canvas.drawBitmap(src, 0, 0);
93    *result = device->accessBitmap(false);
94    offset->fX = bounds.fLeft;
95    offset->fY = bounds.fTop;
96    return true;
97}
98
99void SkDropShadowImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const {
100    if (getInput(0)) {
101        getInput(0)->computeFastBounds(src, dst);
102    } else {
103        *dst = src;
104    }
105
106    SkRect shadowBounds = *dst;
107    shadowBounds.offset(fDx, fDy);
108    shadowBounds.outset(SkScalarMul(fSigmaX, SkIntToScalar(3)),
109                        SkScalarMul(fSigmaY, SkIntToScalar(3)));
110    dst->join(shadowBounds);
111}
112