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                                                  ShadowMode shadowMode, SkImageFilter* input,
     21                                                  const CropRect* cropRect)
     22     : INHERITED(1, &input, cropRect)
     23     , fDx(dx)
     24     , fDy(dy)
     25     , fSigmaX(sigmaX)
     26     , fSigmaY(sigmaY)
     27     , fColor(color)
     28     , fShadowMode(shadowMode)
     29 {
     30 }
     31 
     32 SkFlattenable* SkDropShadowImageFilter::CreateProc(SkReadBuffer& buffer) {
     33     SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
     34     SkScalar dx = buffer.readScalar();
     35     SkScalar dy = buffer.readScalar();
     36     SkScalar sigmaX = buffer.readScalar();
     37     SkScalar sigmaY = buffer.readScalar();
     38     SkColor color = buffer.readColor();
     39     ShadowMode shadowMode = buffer.isVersionLT(SkReadBuffer::kDropShadowMode_Version) ?
     40                             kDrawShadowAndForeground_ShadowMode :
     41                             static_cast<ShadowMode>(buffer.readInt());
     42     return Create(dx, dy, sigmaX, sigmaY, color, shadowMode, common.getInput(0),
     43                   &common.cropRect());
     44 }
     45 
     46 void SkDropShadowImageFilter::flatten(SkWriteBuffer& buffer) const {
     47     this->INHERITED::flatten(buffer);
     48     buffer.writeScalar(fDx);
     49     buffer.writeScalar(fDy);
     50     buffer.writeScalar(fSigmaX);
     51     buffer.writeScalar(fSigmaY);
     52     buffer.writeColor(fColor);
     53     buffer.writeInt(static_cast<int>(fShadowMode));
     54 }
     55 
     56 bool SkDropShadowImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source,
     57                                             const Context& ctx,
     58                                             SkBitmap* result, SkIPoint* offset) const
     59 {
     60     SkBitmap src = source;
     61     SkIPoint srcOffset = SkIPoint::Make(0, 0);
     62     if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctx, &src, &srcOffset))
     63         return false;
     64 
     65     SkIRect bounds;
     66     if (!this->applyCropRect(ctx, src, srcOffset, &bounds)) {
     67         return false;
     68     }
     69 
     70     SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
     71     if (NULL == device.get()) {
     72         return false;
     73     }
     74     SkCanvas canvas(device.get());
     75 
     76     SkVector sigma = SkVector::Make(fSigmaX, fSigmaY);
     77     ctx.ctm().mapVectors(&sigma, 1);
     78     sigma.fX = SkMaxScalar(0, sigma.fX);
     79     sigma.fY = SkMaxScalar(0, sigma.fY);
     80     SkAutoTUnref<SkImageFilter> blurFilter(SkBlurImageFilter::Create(sigma.fX, sigma.fY));
     81     SkAutoTUnref<SkColorFilter> colorFilter(
     82         SkColorFilter::CreateModeFilter(fColor, SkXfermode::kSrcIn_Mode));
     83     SkPaint paint;
     84     paint.setImageFilter(blurFilter.get());
     85     paint.setColorFilter(colorFilter.get());
     86     paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
     87     SkVector offsetVec = SkVector::Make(fDx, fDy);
     88     ctx.ctm().mapVectors(&offsetVec, 1);
     89     canvas.translate(SkIntToScalar(srcOffset.fX - bounds.fLeft),
     90                      SkIntToScalar(srcOffset.fY - bounds.fTop));
     91     canvas.drawBitmap(src, offsetVec.fX, offsetVec.fY, &paint);
     92     if (fShadowMode == kDrawShadowAndForeground_ShadowMode) {
     93         canvas.drawBitmap(src, 0, 0);
     94     }
     95     *result = device->accessBitmap(false);
     96     offset->fX = bounds.fLeft;
     97     offset->fY = bounds.fTop;
     98     return true;
     99 }
    100 
    101 void SkDropShadowImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const {
    102     if (getInput(0)) {
    103         getInput(0)->computeFastBounds(src, dst);
    104     } else {
    105         *dst = src;
    106     }
    107 
    108     SkRect shadowBounds = *dst;
    109     shadowBounds.offset(fDx, fDy);
    110     shadowBounds.outset(SkScalarMul(fSigmaX, SkIntToScalar(3)),
    111                         SkScalarMul(fSigmaY, SkIntToScalar(3)));
    112     if (fShadowMode == kDrawShadowAndForeground_ShadowMode) {
    113         dst->join(shadowBounds);
    114     } else {
    115         *dst = shadowBounds;
    116     }
    117 }
    118 
    119 bool SkDropShadowImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
    120                                              SkIRect* dst) const {
    121     SkIRect bounds = src;
    122     SkVector offsetVec = SkVector::Make(fDx, fDy);
    123     ctm.mapVectors(&offsetVec, 1);
    124     bounds.offset(-SkScalarCeilToInt(offsetVec.x()),
    125                   -SkScalarCeilToInt(offsetVec.y()));
    126     SkVector sigma = SkVector::Make(fSigmaX, fSigmaY);
    127     ctm.mapVectors(&sigma, 1);
    128     bounds.outset(SkScalarCeilToInt(SkScalarMul(sigma.x(), SkIntToScalar(3))),
    129                   SkScalarCeilToInt(SkScalarMul(sigma.y(), SkIntToScalar(3))));
    130     if (fShadowMode == kDrawShadowAndForeground_ShadowMode) {
    131         bounds.join(src);
    132     }
    133     if (getInput(0) && !getInput(0)->filterBounds(bounds, ctm, &bounds)) {
    134         return false;
    135     }
    136     *dst = bounds;
    137     return true;
    138 }
    139 
    140 #ifndef SK_IGNORE_TO_STRING
    141 void SkDropShadowImageFilter::toString(SkString* str) const {
    142     str->appendf("SkDropShadowImageFilter: (");
    143 
    144     str->appendf("dX: %f ", fDx);
    145     str->appendf("dY: %f ", fDy);
    146     str->appendf("sigmaX: %f ", fSigmaX);
    147     str->appendf("sigmaY: %f ", fSigmaY);
    148 
    149     str->append("Color: ");
    150     str->appendHex(fColor);
    151 
    152     static const char* gModeStrings[] = {
    153         "kDrawShadowAndForeground", "kDrawShadowOnly"
    154     };
    155 
    156     SK_COMPILE_ASSERT(kShadowModeCount == SK_ARRAY_COUNT(gModeStrings), enum_mismatch);
    157 
    158     str->appendf(" mode: %s", gModeStrings[fShadowMode]);
    159 
    160     str->append(")");
    161 }
    162 #endif
    163