blob: fc9e47b0b4fa9a2c563af6dfdc11ae74009f0959 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
reed@google.comdaaafa62014-04-29 15:20:16 +00007
reed@android.com8a1c16f2008-12-17 15:59:43 +00008#include "SkBlurDrawLooper.h"
robertphillips@google.com7ce661d2013-08-27 16:14:03 +00009#include "SkBlurMask.h" // just for SkBlurMask::ConvertRadiusToSigma
reed@android.com8a1c16f2008-12-17 15:59:43 +000010#include "SkBlurMaskFilter.h"
11#include "SkCanvas.h"
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000012#include "SkColorFilter.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000013#include "SkReadBuffer.h"
14#include "SkWriteBuffer.h"
robertphillips@google.com4991b8f2013-01-28 20:21:59 +000015#include "SkMaskFilter.h"
16#include "SkPaint.h"
17#include "SkString.h"
18#include "SkStringUtils.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000019
skia.committer@gmail.com7bd141d2013-08-28 07:01:18 +000020SkBlurDrawLooper::SkBlurDrawLooper(SkColor color, SkScalar sigma,
robertphillips@google.com7ce661d2013-08-27 16:14:03 +000021 SkScalar dx, SkScalar dy, uint32_t flags) {
22 this->init(sigma, dx, dy, color, flags);
23}
24
reed@google.comdaaafa62014-04-29 15:20:16 +000025// only call from constructor
26void SkBlurDrawLooper::initEffects() {
27 SkASSERT(fBlurFlags <= kAll_BlurFlag);
28 if (fSigma > 0) {
29 uint32_t flags = fBlurFlags & kIgnoreTransform_BlurFlag ?
30 SkBlurMaskFilter::kIgnoreTransform_BlurFlag :
31 SkBlurMaskFilter::kNone_BlurFlag;
skia.committer@gmail.comeeaeafe2014-04-30 03:05:25 +000032
reed@google.comdaaafa62014-04-29 15:20:16 +000033 flags |= fBlurFlags & kHighQuality_BlurFlag ?
34 SkBlurMaskFilter::kHighQuality_BlurFlag :
35 SkBlurMaskFilter::kNone_BlurFlag;
skia.committer@gmail.comeeaeafe2014-04-30 03:05:25 +000036
reed@google.comdaaafa62014-04-29 15:20:16 +000037 fBlur = SkBlurMaskFilter::Create(kNormal_SkBlurStyle, fSigma, flags);
reed@google.com4e2b3d32011-04-07 14:18:59 +000038 } else {
reed@android.com8a1c16f2008-12-17 15:59:43 +000039 fBlur = NULL;
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000040 }
skia.committer@gmail.comeeaeafe2014-04-30 03:05:25 +000041
reed@google.comdaaafa62014-04-29 15:20:16 +000042 if (fBlurFlags & kOverrideColor_BlurFlag) {
junov@google.coma6398912011-03-11 16:45:00 +000043 // Set alpha to 1 for the override since transparency will already
44 // be baked into the blurred mask.
reed@google.comdaaafa62014-04-29 15:20:16 +000045 SkColor opaqueColor = SkColorSetA(fBlurColor, 255);
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000046 //The SrcIn xfer mode will multiply 'color' by the incoming alpha
reed@google.com4e2b3d32011-04-07 14:18:59 +000047 fColorFilter = SkColorFilter::CreateModeFilter(opaqueColor,
48 SkXfermode::kSrcIn_Mode);
49 } else {
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000050 fColorFilter = NULL;
51 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000052}
53
reed@google.comdaaafa62014-04-29 15:20:16 +000054void SkBlurDrawLooper::init(SkScalar sigma, SkScalar dx, SkScalar dy,
55 SkColor color, uint32_t flags) {
56 fSigma = sigma;
57 fDx = dx;
58 fDy = dy;
59 fBlurColor = color;
60 fBlurFlags = flags;
reed@google.com6bac9472011-06-21 19:24:00 +000061
reed@google.comdaaafa62014-04-29 15:20:16 +000062 this->initEffects();
63}
64
reed9fa60da2014-08-21 07:59:51 -070065#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
reed@google.comdaaafa62014-04-29 15:20:16 +000066SkBlurDrawLooper::SkBlurDrawLooper(SkReadBuffer& buffer) : INHERITED(buffer) {
67
68 fSigma = buffer.readScalar();
reed@android.com8a1c16f2008-12-17 15:59:43 +000069 fDx = buffer.readScalar();
70 fDy = buffer.readScalar();
djsollen@google.comc73dd5c2012-08-07 15:54:32 +000071 fBlurColor = buffer.readColor();
djsollen@google.comc73dd5c2012-08-07 15:54:32 +000072 fBlurFlags = buffer.readUInt() & kAll_BlurFlag;
reed@google.comdaaafa62014-04-29 15:20:16 +000073
74 this->initEffects();
75}
reed9fa60da2014-08-21 07:59:51 -070076#endif
77
78SkFlattenable* SkBlurDrawLooper::CreateProc(SkReadBuffer& buffer) {
79 const SkColor color = buffer.readColor();
80 const SkScalar sigma = buffer.readScalar();
81 const SkScalar dx = buffer.readScalar();
82 const SkScalar dy = buffer.readScalar();
83 const uint32_t flags = buffer.read32();
84 return Create(color, sigma, dx, dy, flags);
85}
reed@google.comdaaafa62014-04-29 15:20:16 +000086
87void SkBlurDrawLooper::flatten(SkWriteBuffer& buffer) const {
reed9fa60da2014-08-21 07:59:51 -070088 buffer.writeColor(fBlurColor);
reed@google.comdaaafa62014-04-29 15:20:16 +000089 buffer.writeScalar(fSigma);
90 buffer.writeScalar(fDx);
91 buffer.writeScalar(fDy);
reed@google.comdaaafa62014-04-29 15:20:16 +000092 buffer.write32(fBlurFlags);
reed@android.com8a1c16f2008-12-17 15:59:43 +000093}
94
reed@google.com4e2b3d32011-04-07 14:18:59 +000095SkBlurDrawLooper::~SkBlurDrawLooper() {
reed@google.com82065d62011-02-07 15:30:46 +000096 SkSafeUnref(fBlur);
senorblanco@chromium.org4868e6b2011-02-18 19:03:01 +000097 SkSafeUnref(fColorFilter);
reed@android.com8a1c16f2008-12-17 15:59:43 +000098}
99
reed@google.comdaaafa62014-04-29 15:20:16 +0000100bool SkBlurDrawLooper::asABlurShadow(BlurShadowRec* rec) const {
101 if (fSigma <= 0 || (fBlurFlags & fBlurFlags & kIgnoreTransform_BlurFlag)) {
102 return false;
103 }
104
105 if (rec) {
106 rec->fSigma = fSigma;
107 rec->fColor = fBlurColor;
108 rec->fOffset.set(fDx, fDy);
109 rec->fStyle = kNormal_SkBlurStyle;
110 rec->fQuality = (fBlurFlags & kHighQuality_BlurFlag) ?
111 kHigh_SkBlurQuality : kLow_SkBlurQuality;
112 }
113 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000114}
115
reed@google.comdaaafa62014-04-29 15:20:16 +0000116////////////////////////////////////////////////////////////////////////////////////////
117
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000118SkDrawLooper::Context* SkBlurDrawLooper::createContext(SkCanvas*, void* storage) const {
119 return SkNEW_PLACEMENT_ARGS(storage, BlurDrawLooperContext, (this));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000120}
121
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000122SkBlurDrawLooper::BlurDrawLooperContext::BlurDrawLooperContext(
123 const SkBlurDrawLooper* looper)
124 : fLooper(looper), fState(SkBlurDrawLooper::kBeforeEdge) {}
125
126bool SkBlurDrawLooper::BlurDrawLooperContext::next(SkCanvas* canvas,
127 SkPaint* paint) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000128 switch (fState) {
reed@google.com4e2b3d32011-04-07 14:18:59 +0000129 case kBeforeEdge:
130 // we do nothing if a maskfilter is already installed
131 if (paint->getMaskFilter()) {
132 fState = kDone;
133 return false;
134 }
djsollen@google.com56c69772011-11-08 19:00:26 +0000135#ifdef SK_BUILD_FOR_ANDROID
djsollen@google.comf5dbe2f2011-04-15 13:41:26 +0000136 SkColor blurColor;
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000137 blurColor = fLooper->fBlurColor;
djsollen@google.comf5dbe2f2011-04-15 13:41:26 +0000138 if (SkColorGetA(blurColor) == 255) {
139 blurColor = SkColorSetA(blurColor, paint->getAlpha());
140 }
141 paint->setColor(blurColor);
142#else
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000143 paint->setColor(fLooper->fBlurColor);
djsollen@google.comf5dbe2f2011-04-15 13:41:26 +0000144#endif
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000145 paint->setMaskFilter(fLooper->fBlur);
146 paint->setColorFilter(fLooper->fColorFilter);
commit-bot@chromium.org74e608c2014-04-23 19:26:38 +0000147 canvas->save();
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000148 if (fLooper->fBlurFlags & kIgnoreTransform_BlurFlag) {
reed@google.com4e2b3d32011-04-07 14:18:59 +0000149 SkMatrix transform(canvas->getTotalMatrix());
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000150 transform.postTranslate(fLooper->fDx, fLooper->fDy);
reed@google.com4e2b3d32011-04-07 14:18:59 +0000151 canvas->setMatrix(transform);
152 } else {
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000153 canvas->translate(fLooper->fDx, fLooper->fDy);
reed@google.com4e2b3d32011-04-07 14:18:59 +0000154 }
155 fState = kAfterEdge;
156 return true;
157 case kAfterEdge:
158 canvas->restore();
159 fState = kDone;
160 return true;
161 default:
162 SkASSERT(kDone == fState);
163 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000164 }
165}
robertphillips@google.com4991b8f2013-01-28 20:21:59 +0000166
commit-bot@chromium.org0f10f7b2014-03-13 18:02:17 +0000167#ifndef SK_IGNORE_TO_STRING
robertphillips@google.com4991b8f2013-01-28 20:21:59 +0000168void SkBlurDrawLooper::toString(SkString* str) const {
169 str->append("SkBlurDrawLooper: ");
170
171 str->append("dx: ");
172 str->appendScalar(fDx);
173
174 str->append(" dy: ");
175 str->appendScalar(fDy);
176
177 str->append(" color: ");
178 str->appendHex(fBlurColor);
179
180 str->append(" flags: (");
181 if (kNone_BlurFlag == fBlurFlags) {
182 str->append("None");
183 } else {
184 bool needsSeparator = false;
skia.committer@gmail.comcdcb2ce2013-01-29 07:05:52 +0000185 SkAddFlagToString(str, SkToBool(kIgnoreTransform_BlurFlag & fBlurFlags), "IgnoreTransform",
robertphillips@google.com4991b8f2013-01-28 20:21:59 +0000186 &needsSeparator);
187 SkAddFlagToString(str, SkToBool(kOverrideColor_BlurFlag & fBlurFlags), "OverrideColor",
188 &needsSeparator);
skia.committer@gmail.comcdcb2ce2013-01-29 07:05:52 +0000189 SkAddFlagToString(str, SkToBool(kHighQuality_BlurFlag & fBlurFlags), "HighQuality",
robertphillips@google.com4991b8f2013-01-28 20:21:59 +0000190 &needsSeparator);
191 }
192 str->append(")");
193
194 // TODO: add optional "fBlurFilter->toString(str);" when SkMaskFilter::toString is added
195 // alternatively we could cache the radius in SkBlurDrawLooper and just add it here
196}
197#endif