Home | History | Annotate | Download | only in effects
      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 
     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 
     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 
     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 
     54 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 
     64 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 
    107 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 
    121 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