Home | History | Annotate | Download | only in effects
      1 
      2 /*
      3  * Copyright 2011 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 #include "SkBlurDrawLooper.h"
      9 #include "SkBlurMaskFilter.h"
     10 #include "SkCanvas.h"
     11 #include "SkColorFilter.h"
     12 #include "SkFlattenableBuffers.h"
     13 #include "SkMaskFilter.h"
     14 #include "SkPaint.h"
     15 #include "SkString.h"
     16 #include "SkStringUtils.h"
     17 
     18 SkBlurDrawLooper::SkBlurDrawLooper(SkScalar radius, SkScalar dx, SkScalar dy,
     19                                    SkColor color, uint32_t flags)
     20     : fDx(dx), fDy(dy), fBlurColor(color), fBlurFlags(flags), fState(kDone) {
     21 
     22     SkASSERT(flags <= kAll_BlurFlag);
     23     if (radius > 0) {
     24         uint32_t blurFlags = flags & kIgnoreTransform_BlurFlag ?
     25             SkBlurMaskFilter::kIgnoreTransform_BlurFlag :
     26             SkBlurMaskFilter::kNone_BlurFlag;
     27 
     28         blurFlags |= flags & kHighQuality_BlurFlag ?
     29             SkBlurMaskFilter::kHighQuality_BlurFlag :
     30             SkBlurMaskFilter::kNone_BlurFlag;
     31 
     32         fBlur = SkBlurMaskFilter::Create(radius,
     33                                          SkBlurMaskFilter::kNormal_BlurStyle,
     34                                          blurFlags);
     35     } else {
     36         fBlur = NULL;
     37     }
     38 
     39     if (flags & kOverrideColor_BlurFlag) {
     40         // Set alpha to 1 for the override since transparency will already
     41         // be baked into the blurred mask.
     42         SkColor opaqueColor = SkColorSetA(color, 255);
     43         //The SrcIn xfer mode will multiply 'color' by the incoming alpha
     44         fColorFilter = SkColorFilter::CreateModeFilter(opaqueColor,
     45                                                        SkXfermode::kSrcIn_Mode);
     46     } else {
     47         fColorFilter = NULL;
     48     }
     49 }
     50 
     51 SkBlurDrawLooper::SkBlurDrawLooper(SkFlattenableReadBuffer& buffer)
     52 : INHERITED(buffer) {
     53 
     54     fDx = buffer.readScalar();
     55     fDy = buffer.readScalar();
     56     fBlurColor = buffer.readColor();
     57     fBlur = buffer.readFlattenableT<SkMaskFilter>();
     58     fColorFilter = buffer.readFlattenableT<SkColorFilter>();
     59     fBlurFlags = buffer.readUInt() & kAll_BlurFlag;
     60 }
     61 
     62 SkBlurDrawLooper::~SkBlurDrawLooper() {
     63     SkSafeUnref(fBlur);
     64     SkSafeUnref(fColorFilter);
     65 }
     66 
     67 void SkBlurDrawLooper::flatten(SkFlattenableWriteBuffer& buffer) const {
     68     this->INHERITED::flatten(buffer);
     69     buffer.writeScalar(fDx);
     70     buffer.writeScalar(fDy);
     71     buffer.writeColor(fBlurColor);
     72     buffer.writeFlattenable(fBlur);
     73     buffer.writeFlattenable(fColorFilter);
     74     buffer.writeUInt(fBlurFlags);
     75 }
     76 
     77 void SkBlurDrawLooper::init(SkCanvas*) {
     78     fState = kBeforeEdge;
     79 }
     80 
     81 bool SkBlurDrawLooper::next(SkCanvas* canvas, SkPaint* paint) {
     82     switch (fState) {
     83         case kBeforeEdge:
     84             // we do nothing if a maskfilter is already installed
     85             if (paint->getMaskFilter()) {
     86                 fState = kDone;
     87                 return false;
     88             }
     89 #ifdef SK_BUILD_FOR_ANDROID
     90             SkColor blurColor;
     91             blurColor = fBlurColor;
     92             if (SkColorGetA(blurColor) == 255) {
     93                 blurColor = SkColorSetA(blurColor, paint->getAlpha());
     94             }
     95             paint->setColor(blurColor);
     96 #else
     97             paint->setColor(fBlurColor);
     98 #endif
     99             paint->setMaskFilter(fBlur);
    100             paint->setColorFilter(fColorFilter);
    101             canvas->save(SkCanvas::kMatrix_SaveFlag);
    102             if (fBlurFlags & kIgnoreTransform_BlurFlag) {
    103                 SkMatrix transform(canvas->getTotalMatrix());
    104                 transform.postTranslate(fDx, fDy);
    105                 canvas->setMatrix(transform);
    106             } else {
    107                 canvas->translate(fDx, fDy);
    108             }
    109             fState = kAfterEdge;
    110             return true;
    111         case kAfterEdge:
    112             canvas->restore();
    113             fState = kDone;
    114             return true;
    115         default:
    116             SkASSERT(kDone == fState);
    117             return false;
    118     }
    119 }
    120 
    121 #ifdef SK_DEVELOPER
    122 void SkBlurDrawLooper::toString(SkString* str) const {
    123     str->append("SkBlurDrawLooper: ");
    124 
    125     str->append("dx: ");
    126     str->appendScalar(fDx);
    127 
    128     str->append(" dy: ");
    129     str->appendScalar(fDy);
    130 
    131     str->append(" color: ");
    132     str->appendHex(fBlurColor);
    133 
    134     str->append(" flags: (");
    135     if (kNone_BlurFlag == fBlurFlags) {
    136         str->append("None");
    137     } else {
    138         bool needsSeparator = false;
    139         SkAddFlagToString(str, SkToBool(kIgnoreTransform_BlurFlag & fBlurFlags), "IgnoreTransform",
    140                           &needsSeparator);
    141         SkAddFlagToString(str, SkToBool(kOverrideColor_BlurFlag & fBlurFlags), "OverrideColor",
    142                           &needsSeparator);
    143         SkAddFlagToString(str, SkToBool(kHighQuality_BlurFlag & fBlurFlags), "HighQuality",
    144                           &needsSeparator);
    145     }
    146     str->append(")");
    147 
    148     // TODO: add optional "fBlurFilter->toString(str);" when SkMaskFilter::toString is added
    149     // alternatively we could cache the radius in SkBlurDrawLooper and just add it here
    150 }
    151 #endif
    152