blob: dda20638a3f5201cf65d9ba69d10d1b7bbbb9569 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
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 */
reed@android.com8a1c16f2008-12-17 15:59:43 +00008#include "SkBlurDrawLooper.h"
9#include "SkBlurMaskFilter.h"
10#include "SkCanvas.h"
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000011#include "SkColorFilter.h"
robertphillips@google.com4991b8f2013-01-28 20:21:59 +000012#include "SkFlattenableBuffers.h"
13#include "SkMaskFilter.h"
14#include "SkPaint.h"
15#include "SkString.h"
16#include "SkStringUtils.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000017
18SkBlurDrawLooper::SkBlurDrawLooper(SkScalar radius, SkScalar dx, SkScalar dy,
senorblanco@chromium.org038aff62010-12-06 23:45:58 +000019 SkColor color, uint32_t flags)
vandebo@chromium.orga728e352012-03-28 20:29:38 +000020 : fDx(dx), fDy(dy), fBlurColor(color), fBlurFlags(flags), fState(kDone) {
reed@google.com4e2b3d32011-04-07 14:18:59 +000021
senorblanco@chromium.org038aff62010-12-06 23:45:58 +000022 SkASSERT(flags <= kAll_BlurFlag);
reed@google.com4e2b3d32011-04-07 14:18:59 +000023 if (radius > 0) {
reed@google.com82065d62011-02-07 15:30:46 +000024 uint32_t blurFlags = flags & kIgnoreTransform_BlurFlag ?
25 SkBlurMaskFilter::kIgnoreTransform_BlurFlag :
senorblanco@chromium.org038aff62010-12-06 23:45:58 +000026 SkBlurMaskFilter::kNone_BlurFlag;
27
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000028 blurFlags |= flags & kHighQuality_BlurFlag ?
rmistry@google.comfbfcd562012-08-23 18:09:54 +000029 SkBlurMaskFilter::kHighQuality_BlurFlag :
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000030 SkBlurMaskFilter::kNone_BlurFlag;
31
reed@android.com8a1c16f2008-12-17 15:59:43 +000032 fBlur = SkBlurMaskFilter::Create(radius,
rmistry@google.comfbfcd562012-08-23 18:09:54 +000033 SkBlurMaskFilter::kNormal_BlurStyle,
senorblanco@chromium.org038aff62010-12-06 23:45:58 +000034 blurFlags);
reed@google.com4e2b3d32011-04-07 14:18:59 +000035 } else {
reed@android.com8a1c16f2008-12-17 15:59:43 +000036 fBlur = NULL;
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000037 }
38
reed@google.com4e2b3d32011-04-07 14:18:59 +000039 if (flags & kOverrideColor_BlurFlag) {
junov@google.coma6398912011-03-11 16:45:00 +000040 // Set alpha to 1 for the override since transparency will already
41 // be baked into the blurred mask.
42 SkColor opaqueColor = SkColorSetA(color, 255);
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000043 //The SrcIn xfer mode will multiply 'color' by the incoming alpha
reed@google.com4e2b3d32011-04-07 14:18:59 +000044 fColorFilter = SkColorFilter::CreateModeFilter(opaqueColor,
45 SkXfermode::kSrcIn_Mode);
46 } else {
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000047 fColorFilter = NULL;
48 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000049}
50
reed@google.com6bac9472011-06-21 19:24:00 +000051SkBlurDrawLooper::SkBlurDrawLooper(SkFlattenableReadBuffer& buffer)
52: INHERITED(buffer) {
53
reed@android.com8a1c16f2008-12-17 15:59:43 +000054 fDx = buffer.readScalar();
55 fDy = buffer.readScalar();
djsollen@google.comc73dd5c2012-08-07 15:54:32 +000056 fBlurColor = buffer.readColor();
57 fBlur = buffer.readFlattenableT<SkMaskFilter>();
58 fColorFilter = buffer.readFlattenableT<SkColorFilter>();
59 fBlurFlags = buffer.readUInt() & kAll_BlurFlag;
reed@android.com8a1c16f2008-12-17 15:59:43 +000060}
61
reed@google.com4e2b3d32011-04-07 14:18:59 +000062SkBlurDrawLooper::~SkBlurDrawLooper() {
reed@google.com82065d62011-02-07 15:30:46 +000063 SkSafeUnref(fBlur);
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000064 SkSafeUnref(fColorFilter);
reed@android.com8a1c16f2008-12-17 15:59:43 +000065}
66
djsollen@google.com54924242012-03-29 15:18:04 +000067void SkBlurDrawLooper::flatten(SkFlattenableWriteBuffer& buffer) const {
68 this->INHERITED::flatten(buffer);
reed@android.com8a1c16f2008-12-17 15:59:43 +000069 buffer.writeScalar(fDx);
70 buffer.writeScalar(fDy);
djsollen@google.comc73dd5c2012-08-07 15:54:32 +000071 buffer.writeColor(fBlurColor);
reed@android.com8a1c16f2008-12-17 15:59:43 +000072 buffer.writeFlattenable(fBlur);
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000073 buffer.writeFlattenable(fColorFilter);
djsollen@google.comc73dd5c2012-08-07 15:54:32 +000074 buffer.writeUInt(fBlurFlags);
reed@android.com8a1c16f2008-12-17 15:59:43 +000075}
76
reed@google.com4e2b3d32011-04-07 14:18:59 +000077void SkBlurDrawLooper::init(SkCanvas* canvas) {
78 fState = kBeforeEdge;
reed@android.com8a1c16f2008-12-17 15:59:43 +000079}
80
reed@google.com4e2b3d32011-04-07 14:18:59 +000081bool SkBlurDrawLooper::next(SkCanvas* canvas, SkPaint* paint) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000082 switch (fState) {
reed@google.com4e2b3d32011-04-07 14:18:59 +000083 case kBeforeEdge:
84 // we do nothing if a maskfilter is already installed
85 if (paint->getMaskFilter()) {
86 fState = kDone;
87 return false;
88 }
djsollen@google.com56c69772011-11-08 19:00:26 +000089#ifdef SK_BUILD_FOR_ANDROID
djsollen@google.comf5dbe2f2011-04-15 13:41:26 +000090 SkColor blurColor;
91 blurColor = fBlurColor;
92 if (SkColorGetA(blurColor) == 255) {
93 blurColor = SkColorSetA(blurColor, paint->getAlpha());
94 }
95 paint->setColor(blurColor);
96#else
reed@google.com4e2b3d32011-04-07 14:18:59 +000097 paint->setColor(fBlurColor);
djsollen@google.comf5dbe2f2011-04-15 13:41:26 +000098#endif
reed@google.com4e2b3d32011-04-07 14:18:59 +000099 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;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000118 }
119}
robertphillips@google.com4991b8f2013-01-28 20:21:59 +0000120
121#ifdef SK_DEVELOPER
122void 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