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