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