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,
     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
     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 
     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 
     56 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 
     65 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 
    108 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 
    122 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