blob: faaecb84fb8f4e2d4abafd6e0f4b6524940df5f1 [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)
10 : fDx(dx), fDy(dy), fBlurColor(color), fBlurFlags(flags)
reed@android.com8a1c16f2008-12-17 15:59:43 +000011{
senorblanco@chromium.org038aff62010-12-06 23:45:58 +000012 SkASSERT(flags <= kAll_BlurFlag);
reed@android.com8a1c16f2008-12-17 15:59:43 +000013 if (radius > 0)
senorblanco@chromium.org038aff62010-12-06 23:45:58 +000014 {
reed@google.com82065d62011-02-07 15:30:46 +000015 uint32_t blurFlags = flags & kIgnoreTransform_BlurFlag ?
16 SkBlurMaskFilter::kIgnoreTransform_BlurFlag :
senorblanco@chromium.org038aff62010-12-06 23:45:58 +000017 SkBlurMaskFilter::kNone_BlurFlag;
18
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000019 blurFlags |= flags & kHighQuality_BlurFlag ?
20 SkBlurMaskFilter::kHighQuality_BlurFlag :
21 SkBlurMaskFilter::kNone_BlurFlag;
22
reed@android.com8a1c16f2008-12-17 15:59:43 +000023 fBlur = SkBlurMaskFilter::Create(radius,
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000024 SkBlurMaskFilter::kNormal_BlurStyle,
senorblanco@chromium.org038aff62010-12-06 23:45:58 +000025 blurFlags);
26 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000027 else
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000028 {
reed@android.com8a1c16f2008-12-17 15:59:43 +000029 fBlur = NULL;
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000030 }
31
32 if (flags & kOverrideColor_BlurFlag)
33 {
34 //The SrcIn xfer mode will multiply 'color' by the incoming alpha
35 fColorFilter = SkColorFilter::CreateModeFilter(color, SkXfermode::kSrcIn_Mode);
36 }
37 else
38 {
39 fColorFilter = NULL;
40 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000041}
42
43SkBlurDrawLooper::SkBlurDrawLooper(SkFlattenableReadBuffer& buffer)
44{
45 fDx = buffer.readScalar();
46 fDy = buffer.readScalar();
47 fBlurColor = buffer.readU32();
48 fBlur = static_cast<SkMaskFilter*>(buffer.readFlattenable());
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000049 fColorFilter = static_cast<SkColorFilter*>(buffer.readFlattenable());
senorblanco@chromium.org038aff62010-12-06 23:45:58 +000050 fBlurFlags = buffer.readU32() & kAll_BlurFlag;
reed@android.com8a1c16f2008-12-17 15:59:43 +000051}
52
53SkBlurDrawLooper::~SkBlurDrawLooper()
54{
reed@google.com82065d62011-02-07 15:30:46 +000055 SkSafeUnref(fBlur);
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000056 SkSafeUnref(fColorFilter);
reed@android.com8a1c16f2008-12-17 15:59:43 +000057}
58
59void SkBlurDrawLooper::flatten(SkFlattenableWriteBuffer& buffer)
60{
61 buffer.writeScalar(fDx);
62 buffer.writeScalar(fDy);
63 buffer.write32(fBlurColor);
64 buffer.writeFlattenable(fBlur);
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000065 buffer.writeFlattenable(fColorFilter);
senorblanco@chromium.org038aff62010-12-06 23:45:58 +000066 buffer.write32(fBlurFlags);
reed@android.com8a1c16f2008-12-17 15:59:43 +000067}
68
69void SkBlurDrawLooper::init(SkCanvas* canvas, SkPaint* paint)
70{
71 // we do nothing if a maskfilter is already installed
72 if (paint->getMaskFilter() != NULL)
73 fState = kDone;
74 else
75 {
76 fState = kBeforeEdge;
77 fPaint = paint;
78 fCanvas = canvas;
79 fSaveCount = canvas->getSaveCount();
80 }
81}
82
83bool SkBlurDrawLooper::next()
84{
85 switch (fState) {
86 case kBeforeEdge:
87 fSavedColor = fPaint->getColor();
88 fPaint->setColor(fBlurColor);
89 fPaint->setMaskFilter(fBlur);
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000090 fPaint->setColorFilter(fColorFilter);
reed@android.com8a1c16f2008-12-17 15:59:43 +000091 fCanvas->save(SkCanvas::kMatrix_SaveFlag);
senorblanco@chromium.org038aff62010-12-06 23:45:58 +000092 if (fBlurFlags & kIgnoreTransform_BlurFlag)
93 {
94 SkMatrix transform(fCanvas->getTotalMatrix());
95 transform.postTranslate(fDx, fDy);
96 fCanvas->setMatrix(transform);
97 }
98 else
99 {
100 fCanvas->translate(fDx, fDy);
101 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000102 fState = kAfterEdge;
103 return true;
104 case kAfterEdge:
105 fPaint->setColor(fSavedColor);
106 fPaint->setMaskFilter(NULL);
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +0000107 fPaint->setColorFilter(NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000108 fCanvas->restore(); // to remove the translate we did earlier
109 fState = kDone;
110 return true;
111 default:
112 SkASSERT(kDone == fState);
113 return false;
114 }
115}
116
117void SkBlurDrawLooper::restore()
118{
119 if (kAfterEdge == fState)
120 {
121 fPaint->setColor(fSavedColor);
122 fPaint->setMaskFilter(NULL);
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +0000123 fPaint->setColorFilter(NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000124 fCanvas->restore(); // to remove the translate we did earlier
125 fState = kDone;
126 }
127}
128
129///////////////////////////////////////////////////////////////////////////////
130
131static SkFlattenable::Registrar gReg("SkBlurDrawLooper",
132 SkBlurDrawLooper::CreateProc);
133