blob: 9290ead766c27c7bc83b99b39b948155e86f412e [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.com4e2b3d32011-04-07 14:18:59 +000041SkBlurDrawLooper::SkBlurDrawLooper(SkFlattenableReadBuffer& buffer) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000042 fDx = buffer.readScalar();
43 fDy = buffer.readScalar();
44 fBlurColor = buffer.readU32();
45 fBlur = static_cast<SkMaskFilter*>(buffer.readFlattenable());
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000046 fColorFilter = static_cast<SkColorFilter*>(buffer.readFlattenable());
senorblanco@chromium.org038aff62010-12-06 23:45:58 +000047 fBlurFlags = buffer.readU32() & kAll_BlurFlag;
reed@android.com8a1c16f2008-12-17 15:59:43 +000048}
49
reed@google.com4e2b3d32011-04-07 14:18:59 +000050SkBlurDrawLooper::~SkBlurDrawLooper() {
reed@google.com82065d62011-02-07 15:30:46 +000051 SkSafeUnref(fBlur);
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000052 SkSafeUnref(fColorFilter);
reed@android.com8a1c16f2008-12-17 15:59:43 +000053}
54
reed@google.com4e2b3d32011-04-07 14:18:59 +000055void SkBlurDrawLooper::flatten(SkFlattenableWriteBuffer& buffer) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000056 buffer.writeScalar(fDx);
57 buffer.writeScalar(fDy);
58 buffer.write32(fBlurColor);
59 buffer.writeFlattenable(fBlur);
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000060 buffer.writeFlattenable(fColorFilter);
senorblanco@chromium.org038aff62010-12-06 23:45:58 +000061 buffer.write32(fBlurFlags);
reed@android.com8a1c16f2008-12-17 15:59:43 +000062}
63
reed@google.com4e2b3d32011-04-07 14:18:59 +000064void SkBlurDrawLooper::init(SkCanvas* canvas) {
65 fState = kBeforeEdge;
reed@android.com8a1c16f2008-12-17 15:59:43 +000066}
67
reed@google.com4e2b3d32011-04-07 14:18:59 +000068bool SkBlurDrawLooper::next(SkCanvas* canvas, SkPaint* paint) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000069 switch (fState) {
reed@google.com4e2b3d32011-04-07 14:18:59 +000070 case kBeforeEdge:
71 // we do nothing if a maskfilter is already installed
72 if (paint->getMaskFilter()) {
73 fState = kDone;
74 return false;
75 }
76 paint->setColor(fBlurColor);
77 paint->setMaskFilter(fBlur);
78 paint->setColorFilter(fColorFilter);
79 canvas->save(SkCanvas::kMatrix_SaveFlag);
80 if (fBlurFlags & kIgnoreTransform_BlurFlag) {
81 SkMatrix transform(canvas->getTotalMatrix());
82 transform.postTranslate(fDx, fDy);
83 canvas->setMatrix(transform);
84 } else {
85 canvas->translate(fDx, fDy);
86 }
87 fState = kAfterEdge;
88 return true;
89 case kAfterEdge:
90 canvas->restore();
91 fState = kDone;
92 return true;
93 default:
94 SkASSERT(kDone == fState);
95 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +000096 }
97}
98
99///////////////////////////////////////////////////////////////////////////////
100
101static SkFlattenable::Registrar gReg("SkBlurDrawLooper",
102 SkBlurDrawLooper::CreateProc);
103