blob: 5089f5926ed48c818de518d558a8173745b5660e [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 {
junov@google.coma6398912011-03-11 16:45:00 +000034 // Set alpha to 1 for the override since transparency will already
35 // be baked into the blurred mask.
36 SkColor opaqueColor = SkColorSetA(color, 255);
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000037 //The SrcIn xfer mode will multiply 'color' by the incoming alpha
junov@google.coma6398912011-03-11 16:45:00 +000038 fColorFilter = SkColorFilter::CreateModeFilter(opaqueColor, SkXfermode::kSrcIn_Mode);
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000039 }
40 else
41 {
42 fColorFilter = NULL;
43 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000044}
45
46SkBlurDrawLooper::SkBlurDrawLooper(SkFlattenableReadBuffer& buffer)
47{
48 fDx = buffer.readScalar();
49 fDy = buffer.readScalar();
50 fBlurColor = buffer.readU32();
51 fBlur = static_cast<SkMaskFilter*>(buffer.readFlattenable());
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000052 fColorFilter = static_cast<SkColorFilter*>(buffer.readFlattenable());
senorblanco@chromium.org038aff62010-12-06 23:45:58 +000053 fBlurFlags = buffer.readU32() & kAll_BlurFlag;
reed@android.com8a1c16f2008-12-17 15:59:43 +000054}
55
56SkBlurDrawLooper::~SkBlurDrawLooper()
57{
reed@google.com82065d62011-02-07 15:30:46 +000058 SkSafeUnref(fBlur);
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000059 SkSafeUnref(fColorFilter);
reed@android.com8a1c16f2008-12-17 15:59:43 +000060}
61
62void SkBlurDrawLooper::flatten(SkFlattenableWriteBuffer& buffer)
63{
64 buffer.writeScalar(fDx);
65 buffer.writeScalar(fDy);
66 buffer.write32(fBlurColor);
67 buffer.writeFlattenable(fBlur);
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000068 buffer.writeFlattenable(fColorFilter);
senorblanco@chromium.org038aff62010-12-06 23:45:58 +000069 buffer.write32(fBlurFlags);
reed@android.com8a1c16f2008-12-17 15:59:43 +000070}
71
72void SkBlurDrawLooper::init(SkCanvas* canvas, SkPaint* paint)
73{
74 // we do nothing if a maskfilter is already installed
75 if (paint->getMaskFilter() != NULL)
76 fState = kDone;
77 else
78 {
79 fState = kBeforeEdge;
80 fPaint = paint;
81 fCanvas = canvas;
82 fSaveCount = canvas->getSaveCount();
83 }
84}
85
86bool SkBlurDrawLooper::next()
87{
88 switch (fState) {
89 case kBeforeEdge:
90 fSavedColor = fPaint->getColor();
91 fPaint->setColor(fBlurColor);
92 fPaint->setMaskFilter(fBlur);
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000093 fPaint->setColorFilter(fColorFilter);
reed@android.com8a1c16f2008-12-17 15:59:43 +000094 fCanvas->save(SkCanvas::kMatrix_SaveFlag);
senorblanco@chromium.org038aff62010-12-06 23:45:58 +000095 if (fBlurFlags & kIgnoreTransform_BlurFlag)
96 {
97 SkMatrix transform(fCanvas->getTotalMatrix());
98 transform.postTranslate(fDx, fDy);
99 fCanvas->setMatrix(transform);
100 }
101 else
102 {
103 fCanvas->translate(fDx, fDy);
104 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000105 fState = kAfterEdge;
106 return true;
107 case kAfterEdge:
108 fPaint->setColor(fSavedColor);
109 fPaint->setMaskFilter(NULL);
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +0000110 fPaint->setColorFilter(NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000111 fCanvas->restore(); // to remove the translate we did earlier
112 fState = kDone;
113 return true;
114 default:
115 SkASSERT(kDone == fState);
116 return false;
117 }
118}
119
120void SkBlurDrawLooper::restore()
121{
122 if (kAfterEdge == fState)
123 {
124 fPaint->setColor(fSavedColor);
125 fPaint->setMaskFilter(NULL);
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +0000126 fPaint->setColorFilter(NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000127 fCanvas->restore(); // to remove the translate we did earlier
128 fState = kDone;
129 }
130}
131
132///////////////////////////////////////////////////////////////////////////////
133
134static SkFlattenable::Registrar gReg("SkBlurDrawLooper",
135 SkBlurDrawLooper::CreateProc);
136