blob: 0672f1bf7cf33f5a5c8d7416735c731b3e73042f [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001#include "SkBlurDrawLooper.h"
2#include "SkBlurMaskFilter.h"
3#include "SkCanvas.h"
4#include "SkPaint.h"
5#include "SkMaskFilter.h"
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +00006#include "SkColorFilter.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +00007
8SkBlurDrawLooper::SkBlurDrawLooper(SkScalar radius, SkScalar dx, SkScalar dy,
senorblanco@chromium.org038aff62010-12-06 23:45:58 +00009 SkColor color, uint32_t flags)
reed@google.com4e2b3d32011-04-07 14:18:59 +000010 : fDx(dx), fDy(dy), fBlurColor(color), fBlurFlags(flags) {
11
senorblanco@chromium.org038aff62010-12-06 23:45:58 +000012 SkASSERT(flags <= kAll_BlurFlag);
reed@google.com4e2b3d32011-04-07 14:18:59 +000013 if (radius > 0) {
reed@google.com82065d62011-02-07 15:30:46 +000014 uint32_t blurFlags = flags & kIgnoreTransform_BlurFlag ?
15 SkBlurMaskFilter::kIgnoreTransform_BlurFlag :
senorblanco@chromium.org038aff62010-12-06 23:45:58 +000016 SkBlurMaskFilter::kNone_BlurFlag;
17
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000018 blurFlags |= flags & kHighQuality_BlurFlag ?
19 SkBlurMaskFilter::kHighQuality_BlurFlag :
20 SkBlurMaskFilter::kNone_BlurFlag;
21
reed@android.com8a1c16f2008-12-17 15:59:43 +000022 fBlur = SkBlurMaskFilter::Create(radius,
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000023 SkBlurMaskFilter::kNormal_BlurStyle,
senorblanco@chromium.org038aff62010-12-06 23:45:58 +000024 blurFlags);
reed@google.com4e2b3d32011-04-07 14:18:59 +000025 } else {
reed@android.com8a1c16f2008-12-17 15:59:43 +000026 fBlur = NULL;
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000027 }
28
reed@google.com4e2b3d32011-04-07 14:18:59 +000029 if (flags & kOverrideColor_BlurFlag) {
junov@google.coma6398912011-03-11 16:45:00 +000030 // Set alpha to 1 for the override since transparency will already
31 // be baked into the blurred mask.
32 SkColor opaqueColor = SkColorSetA(color, 255);
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000033 //The SrcIn xfer mode will multiply 'color' by the incoming alpha
reed@google.com4e2b3d32011-04-07 14:18:59 +000034 fColorFilter = SkColorFilter::CreateModeFilter(opaqueColor,
35 SkXfermode::kSrcIn_Mode);
36 } else {
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000037 fColorFilter = NULL;
38 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000039}
40
reed@google.com6bac9472011-06-21 19:24:00 +000041SkBlurDrawLooper::SkBlurDrawLooper(SkFlattenableReadBuffer& buffer)
42: INHERITED(buffer) {
43
reed@android.com8a1c16f2008-12-17 15:59:43 +000044 fDx = buffer.readScalar();
45 fDy = buffer.readScalar();
46 fBlurColor = buffer.readU32();
47 fBlur = static_cast<SkMaskFilter*>(buffer.readFlattenable());
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000048 fColorFilter = static_cast<SkColorFilter*>(buffer.readFlattenable());
senorblanco@chromium.org038aff62010-12-06 23:45:58 +000049 fBlurFlags = buffer.readU32() & kAll_BlurFlag;
reed@android.com8a1c16f2008-12-17 15:59:43 +000050}
51
reed@google.com4e2b3d32011-04-07 14:18:59 +000052SkBlurDrawLooper::~SkBlurDrawLooper() {
reed@google.com82065d62011-02-07 15:30:46 +000053 SkSafeUnref(fBlur);
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000054 SkSafeUnref(fColorFilter);
reed@android.com8a1c16f2008-12-17 15:59:43 +000055}
56
reed@google.com4e2b3d32011-04-07 14:18:59 +000057void SkBlurDrawLooper::flatten(SkFlattenableWriteBuffer& buffer) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000058 buffer.writeScalar(fDx);
59 buffer.writeScalar(fDy);
60 buffer.write32(fBlurColor);
61 buffer.writeFlattenable(fBlur);
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000062 buffer.writeFlattenable(fColorFilter);
senorblanco@chromium.org038aff62010-12-06 23:45:58 +000063 buffer.write32(fBlurFlags);
reed@android.com8a1c16f2008-12-17 15:59:43 +000064}
65
reed@google.com4e2b3d32011-04-07 14:18:59 +000066void SkBlurDrawLooper::init(SkCanvas* canvas) {
67 fState = kBeforeEdge;
reed@android.com8a1c16f2008-12-17 15:59:43 +000068}
69
reed@google.com4e2b3d32011-04-07 14:18:59 +000070bool SkBlurDrawLooper::next(SkCanvas* canvas, SkPaint* paint) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000071 switch (fState) {
reed@google.com4e2b3d32011-04-07 14:18:59 +000072 case kBeforeEdge:
73 // we do nothing if a maskfilter is already installed
74 if (paint->getMaskFilter()) {
75 fState = kDone;
76 return false;
77 }
djsollen@google.comf5dbe2f2011-04-15 13:41:26 +000078#ifdef ANDROID
79 SkColor blurColor;
80 blurColor = fBlurColor;
81 if (SkColorGetA(blurColor) == 255) {
82 blurColor = SkColorSetA(blurColor, paint->getAlpha());
83 }
84 paint->setColor(blurColor);
85#else
reed@google.com4e2b3d32011-04-07 14:18:59 +000086 paint->setColor(fBlurColor);
djsollen@google.comf5dbe2f2011-04-15 13:41:26 +000087#endif
reed@google.com4e2b3d32011-04-07 14:18:59 +000088 paint->setMaskFilter(fBlur);
89 paint->setColorFilter(fColorFilter);
90 canvas->save(SkCanvas::kMatrix_SaveFlag);
91 if (fBlurFlags & kIgnoreTransform_BlurFlag) {
92 SkMatrix transform(canvas->getTotalMatrix());
93 transform.postTranslate(fDx, fDy);
94 canvas->setMatrix(transform);
95 } else {
96 canvas->translate(fDx, fDy);
97 }
98 fState = kAfterEdge;
99 return true;
100 case kAfterEdge:
101 canvas->restore();
102 fState = kDone;
103 return true;
104 default:
105 SkASSERT(kDone == fState);
106 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000107 }
108}
109
110///////////////////////////////////////////////////////////////////////////////
111
112static SkFlattenable::Registrar gReg("SkBlurDrawLooper",
113 SkBlurDrawLooper::CreateProc);
114