blob: 177a3ba5f0a77a4423caec8ec3a6ce04b67a6a43 [file] [log] [blame]
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +00001/*
2 * Copyright 2013 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 */
7
8#include "SkAlphaThresholdFilter.h"
9#include "SkBitmap.h"
senorblanco1d3ff432015-10-20 10:17:34 -070010#include "SkDevice.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000011#include "SkReadBuffer.h"
12#include "SkWriteBuffer.h"
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +000013#include "SkRegion.h"
robertphillipsea461502015-05-26 11:38:03 -070014#if SK_SUPPORT_GPU
15#include "GrDrawContext.h"
16#endif
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +000017
18class SK_API SkAlphaThresholdFilterImpl : public SkImageFilter {
19public:
senorblanco9ea3d572014-07-08 09:16:22 -070020 SkAlphaThresholdFilterImpl(const SkRegion& region, SkScalar innerThreshold,
21 SkScalar outerThreshold, SkImageFilter* input);
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +000022
robertphillipsf3f5bad2014-12-19 13:49:15 -080023 SK_TO_STRING_OVERRIDE()
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +000024 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkAlphaThresholdFilterImpl)
halcanary07456532015-12-07 10:29:54 -080025 friend void SkAlphaThresholdFilter::InitializeFlattenables();
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +000026
27protected:
mtklein36352bf2015-03-25 18:17:31 -070028 void flatten(SkWriteBuffer&) const override;
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +000029
robertphillips48e78462016-02-17 13:57:16 -080030 bool onFilterImageDeprecated(Proxy*, const SkBitmap& src, const Context&,
31 SkBitmap* result, SkIPoint* offset) const override;
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +000032#if SK_SUPPORT_GPU
bsalomon4a339522015-10-06 08:40:50 -070033 bool asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&,
34 const SkIRect& bounds) const override;
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +000035#endif
36
37private:
38 SkRegion fRegion;
39 SkScalar fInnerThreshold;
40 SkScalar fOuterThreshold;
41 typedef SkImageFilter INHERITED;
42};
43
halcanary07456532015-12-07 10:29:54 -080044SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkAlphaThresholdFilter)
45 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkAlphaThresholdFilterImpl)
46SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
47
reedca726ab2016-02-22 12:50:25 -080048static SkScalar pin_0_1(SkScalar x) {
49 return SkMinScalar(SkMaxScalar(x, 0), 1);
50}
halcanary07456532015-12-07 10:29:54 -080051
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +000052SkImageFilter* SkAlphaThresholdFilter::Create(const SkRegion& region,
53 SkScalar innerThreshold,
senorblanco9ea3d572014-07-08 09:16:22 -070054 SkScalar outerThreshold,
55 SkImageFilter* input) {
reedca726ab2016-02-22 12:50:25 -080056 innerThreshold = pin_0_1(innerThreshold);
57 outerThreshold = pin_0_1(outerThreshold);
58 if (!SkScalarIsFinite(innerThreshold) || !SkScalarIsFinite(outerThreshold)) {
59 return nullptr;
60 }
halcanary385fe4d2015-08-26 13:07:48 -070061 return new SkAlphaThresholdFilterImpl(region, innerThreshold, outerThreshold, input);
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +000062}
63
64#if SK_SUPPORT_GPU
65#include "GrContext.h"
66#include "GrCoordTransform.h"
bsalomon6251d172014-10-15 10:50:36 -070067#include "GrFragmentProcessor.h"
egdaniel605dd0f2014-11-12 08:35:25 -080068#include "GrInvariantOutput.h"
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +000069#include "GrTextureAccess.h"
egdaniel95131432014-12-09 11:15:43 -080070#include "effects/GrPorterDuffXferProcessor.h"
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +000071
72#include "SkGr.h"
73
egdaniel64c47282015-11-13 06:54:19 -080074#include "glsl/GrGLSLFragmentProcessor.h"
egdaniel2d721d32015-11-11 13:06:05 -080075#include "glsl/GrGLSLFragmentShaderBuilder.h"
egdaniel018fb622015-10-28 07:26:40 -070076#include "glsl/GrGLSLProgramDataManager.h"
egdaniel7ea439b2015-12-03 09:20:44 -080077#include "glsl/GrGLSLUniformHandler.h"
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +000078
senorblanco1ea67a32016-01-19 08:50:18 -080079namespace {
80
81SkMatrix make_div_and_translate_matrix(GrTexture* texture, int x, int y) {
82 SkMatrix matrix = GrCoordTransform::MakeDivByTextureWHMatrix(texture);
83 matrix.preTranslate(SkIntToScalar(x), SkIntToScalar(y));
84 return matrix;
85}
86
87};
88
joshualittb0a8a372014-09-23 09:50:21 -070089class AlphaThresholdEffect : public GrFragmentProcessor {
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +000090
91public:
bsalomon4a339522015-10-06 08:40:50 -070092 static GrFragmentProcessor* Create(GrTexture* texture,
joshualittb0a8a372014-09-23 09:50:21 -070093 GrTexture* maskTexture,
94 float innerThreshold,
senorblanco1ea67a32016-01-19 08:50:18 -080095 float outerThreshold,
96 const SkIRect& bounds) {
97 return new AlphaThresholdEffect(texture, maskTexture, innerThreshold, outerThreshold,
98 bounds);
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +000099 }
100
101 virtual ~AlphaThresholdEffect() {};
102
mtklein36352bf2015-03-25 18:17:31 -0700103 const char* name() const override { return "Alpha Threshold"; }
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000104
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000105 float innerThreshold() const { return fInnerThreshold; }
106 float outerThreshold() const { return fOuterThreshold; }
107
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000108private:
bsalomon4a339522015-10-06 08:40:50 -0700109 AlphaThresholdEffect(GrTexture* texture,
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000110 GrTexture* maskTexture,
111 float innerThreshold,
senorblanco1ea67a32016-01-19 08:50:18 -0800112 float outerThreshold,
113 const SkIRect& bounds)
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000114 : fInnerThreshold(innerThreshold)
115 , fOuterThreshold(outerThreshold)
bsalomon6267f812014-08-29 15:05:53 -0700116 , fImageCoordTransform(kLocal_GrCoordSet,
bsalomon9f876a32014-12-09 10:51:07 -0800117 GrCoordTransform::MakeDivByTextureWHMatrix(texture), texture,
118 GrTextureParams::kNone_FilterMode)
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000119 , fImageTextureAccess(texture)
bsalomon6267f812014-08-29 15:05:53 -0700120 , fMaskCoordTransform(kLocal_GrCoordSet,
senorblanco1ea67a32016-01-19 08:50:18 -0800121 make_div_and_translate_matrix(maskTexture, -bounds.x(), -bounds.y()),
122 maskTexture,
bsalomon9f876a32014-12-09 10:51:07 -0800123 GrTextureParams::kNone_FilterMode)
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000124 , fMaskTextureAccess(maskTexture) {
joshualitteb2a6762014-12-04 11:35:33 -0800125 this->initClassID<AlphaThresholdEffect>();
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000126 this->addCoordTransform(&fImageCoordTransform);
127 this->addTextureAccess(&fImageTextureAccess);
128 this->addCoordTransform(&fMaskCoordTransform);
129 this->addTextureAccess(&fMaskTextureAccess);
130 }
131
egdaniel57d3b032015-11-13 11:57:27 -0800132 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700133
egdaniel57d3b032015-11-13 11:57:27 -0800134 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700135
mtklein36352bf2015-03-25 18:17:31 -0700136 bool onIsEqual(const GrFragmentProcessor&) const override;
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000137
mtklein36352bf2015-03-25 18:17:31 -0700138 void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
egdaniel1a8ecdf2014-10-03 06:24:12 -0700139
joshualittb0a8a372014-09-23 09:50:21 -0700140 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000141
142 float fInnerThreshold;
143 float fOuterThreshold;
144 GrCoordTransform fImageCoordTransform;
145 GrTextureAccess fImageTextureAccess;
146 GrCoordTransform fMaskCoordTransform;
147 GrTextureAccess fMaskTextureAccess;
148
joshualittb0a8a372014-09-23 09:50:21 -0700149 typedef GrFragmentProcessor INHERITED;
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000150};
151
egdaniel64c47282015-11-13 06:54:19 -0800152class GrGLAlphaThresholdEffect : public GrGLSLFragmentProcessor {
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000153public:
robertphillips9cdb9922016-02-03 12:25:40 -0800154 void emitCode(EmitArgs&) override;
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000155
wangyixb1daa862015-08-18 11:29:31 -0700156protected:
egdaniel018fb622015-10-28 07:26:40 -0700157 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000158
159private:
egdaniel018fb622015-10-28 07:26:40 -0700160 GrGLSLProgramDataManager::UniformHandle fInnerThresholdVar;
161 GrGLSLProgramDataManager::UniformHandle fOuterThresholdVar;
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000162
egdaniel64c47282015-11-13 06:54:19 -0800163 typedef GrGLSLFragmentProcessor INHERITED;
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000164};
165
wangyix7c157a92015-07-22 15:08:53 -0700166void GrGLAlphaThresholdEffect::emitCode(EmitArgs& args) {
egdaniel7ea439b2015-12-03 09:20:44 -0800167 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
cdalton5e58cee2016-02-11 12:49:47 -0800168 fInnerThresholdVar = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800169 kFloat_GrSLType, kDefault_GrSLPrecision,
170 "inner_threshold");
cdalton5e58cee2016-02-11 12:49:47 -0800171 fOuterThresholdVar = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800172 kFloat_GrSLType, kDefault_GrSLPrecision,
173 "outer_threshold");
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000174
cdalton85285412016-02-18 12:37:07 -0800175 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
egdaniel4ca2e602015-11-18 08:01:26 -0800176 SkString coords2D = fragBuilder->ensureFSCoords2D(args.fCoords, 0);
177 SkString maskCoords2D = fragBuilder->ensureFSCoords2D(args.fCoords, 1);
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000178
egdaniel4ca2e602015-11-18 08:01:26 -0800179 fragBuilder->codeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str());
180 fragBuilder->codeAppendf("\t\tvec2 mask_coord = %s;\n", maskCoords2D.c_str());
181 fragBuilder->codeAppend("\t\tvec4 input_color = ");
182 fragBuilder->appendTextureLookup(args.fSamplers[0], "coord");
183 fragBuilder->codeAppend(";\n");
184 fragBuilder->codeAppend("\t\tvec4 mask_color = ");
185 fragBuilder->appendTextureLookup(args.fSamplers[1], "mask_coord");
186 fragBuilder->codeAppend(";\n");
joshualitt30ba4362014-08-21 20:18:45 -0700187
egdaniel4ca2e602015-11-18 08:01:26 -0800188 fragBuilder->codeAppendf("\t\tfloat inner_thresh = %s;\n",
egdaniel7ea439b2015-12-03 09:20:44 -0800189 uniformHandler->getUniformCStr(fInnerThresholdVar));
egdaniel4ca2e602015-11-18 08:01:26 -0800190 fragBuilder->codeAppendf("\t\tfloat outer_thresh = %s;\n",
egdaniel7ea439b2015-12-03 09:20:44 -0800191 uniformHandler->getUniformCStr(fOuterThresholdVar));
egdaniel4ca2e602015-11-18 08:01:26 -0800192 fragBuilder->codeAppend("\t\tfloat mask = mask_color.a;\n");
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000193
egdaniel4ca2e602015-11-18 08:01:26 -0800194 fragBuilder->codeAppend("vec4 color = input_color;\n");
195 fragBuilder->codeAppend("\t\tif (mask < 0.5) {\n"
196 "\t\t\tif (color.a > outer_thresh) {\n"
197 "\t\t\t\tfloat scale = outer_thresh / color.a;\n"
198 "\t\t\t\tcolor.rgb *= scale;\n"
199 "\t\t\t\tcolor.a = outer_thresh;\n"
200 "\t\t\t}\n"
201 "\t\t} else if (color.a < inner_thresh) {\n"
202 "\t\t\tfloat scale = inner_thresh / max(0.001, color.a);\n"
203 "\t\t\tcolor.rgb *= scale;\n"
204 "\t\t\tcolor.a = inner_thresh;\n"
205 "\t\t}\n");
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000206
egdaniel4ca2e602015-11-18 08:01:26 -0800207 fragBuilder->codeAppendf("%s = %s;\n", args.fOutputColor,
208 (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr4("color")).c_str());
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000209}
210
egdaniel018fb622015-10-28 07:26:40 -0700211void GrGLAlphaThresholdEffect::onSetData(const GrGLSLProgramDataManager& pdman,
joshualittb0a8a372014-09-23 09:50:21 -0700212 const GrProcessor& proc) {
213 const AlphaThresholdEffect& alpha_threshold = proc.cast<AlphaThresholdEffect>();
kkinnunen7510b222014-07-30 00:04:16 -0700214 pdman.set1f(fInnerThresholdVar, alpha_threshold.innerThreshold());
215 pdman.set1f(fOuterThresholdVar, alpha_threshold.outerThreshold());
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000216}
217
218/////////////////////////////////////////////////////////////////////
219
joshualittb0a8a372014-09-23 09:50:21 -0700220GR_DEFINE_FRAGMENT_PROCESSOR_TEST(AlphaThresholdEffect);
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000221
bsalomonc21b09e2015-08-28 18:46:56 -0700222const GrFragmentProcessor* AlphaThresholdEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700223 GrTexture* bmpTex = d->fTextures[GrProcessorUnitTest::kSkiaPMTextureIdx];
224 GrTexture* maskTex = d->fTextures[GrProcessorUnitTest::kAlphaTextureIdx];
225 float innerThresh = d->fRandom->nextUScalar1();
226 float outerThresh = d->fRandom->nextUScalar1();
senorblanco1ea67a32016-01-19 08:50:18 -0800227 const int kMaxWidth = 1000;
228 const int kMaxHeight = 1000;
229 uint32_t width = d->fRandom->nextULessThan(kMaxWidth);
230 uint32_t height = d->fRandom->nextULessThan(kMaxHeight);
231 uint32_t x = d->fRandom->nextULessThan(kMaxWidth - width);
232 uint32_t y = d->fRandom->nextULessThan(kMaxHeight - height);
233 SkIRect bounds = SkIRect::MakeXYWH(x, y, width, height);
234 return AlphaThresholdEffect::Create(bmpTex, maskTex, innerThresh, outerThresh, bounds);
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000235}
236
237///////////////////////////////////////////////////////////////////////////////
238
egdaniel57d3b032015-11-13 11:57:27 -0800239void AlphaThresholdEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
240 GrProcessorKeyBuilder* b) const {
joshualitteb2a6762014-12-04 11:35:33 -0800241 GrGLAlphaThresholdEffect::GenKey(*this, caps, b);
242}
243
egdaniel57d3b032015-11-13 11:57:27 -0800244GrGLSLFragmentProcessor* AlphaThresholdEffect::onCreateGLSLInstance() const {
robertphillips9cdb9922016-02-03 12:25:40 -0800245 return new GrGLAlphaThresholdEffect;
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000246}
247
bsalomon0e08fc12014-10-15 08:19:04 -0700248bool AlphaThresholdEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
joshualitt49586be2014-09-16 08:21:41 -0700249 const AlphaThresholdEffect& s = sBase.cast<AlphaThresholdEffect>();
bsalomon420d7e92014-10-16 09:18:09 -0700250 return (this->fInnerThreshold == s.fInnerThreshold &&
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000251 this->fOuterThreshold == s.fOuterThreshold);
252}
253
egdaniel605dd0f2014-11-12 08:35:25 -0800254void AlphaThresholdEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
egdanielf8449ba2014-11-25 10:24:56 -0800255 if (GrPixelConfigIsAlphaOnly(this->texture(0)->config())) {
joshualitt56995b52014-12-11 15:44:02 -0800256 inout->mulByUnknownSingleComponent();
egdanielf8449ba2014-11-25 10:24:56 -0800257 } else if (GrPixelConfigIsOpaque(this->texture(0)->config()) && fOuterThreshold >= 1.f) {
joshualitt56995b52014-12-11 15:44:02 -0800258 inout->mulByUnknownOpaqueFourComponents();
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000259 } else {
joshualitt56995b52014-12-11 15:44:02 -0800260 inout->mulByUnknownFourComponents();
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000261 }
262}
263
264#endif
265
reed9fa60da2014-08-21 07:59:51 -0700266SkFlattenable* SkAlphaThresholdFilterImpl::CreateProc(SkReadBuffer& buffer) {
267 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
268 SkScalar inner = buffer.readScalar();
269 SkScalar outer = buffer.readScalar();
270 SkRegion rgn;
271 buffer.readRegion(&rgn);
robertphillips2238c9d2016-03-30 13:34:16 -0700272 return SkAlphaThresholdFilter::Create(rgn, inner, outer, common.getInput(0).get());
reed9fa60da2014-08-21 07:59:51 -0700273}
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000274
275SkAlphaThresholdFilterImpl::SkAlphaThresholdFilterImpl(const SkRegion& region,
276 SkScalar innerThreshold,
senorblanco9ea3d572014-07-08 09:16:22 -0700277 SkScalar outerThreshold,
278 SkImageFilter* input)
279 : INHERITED(1, &input)
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000280 , fRegion(region)
281 , fInnerThreshold(innerThreshold)
282 , fOuterThreshold(outerThreshold) {
283}
284
285#if SK_SUPPORT_GPU
joshualittb0a8a372014-09-23 09:50:21 -0700286bool SkAlphaThresholdFilterImpl::asFragmentProcessor(GrFragmentProcessor** fp,
287 GrTexture* texture,
robertphillips2e1e51f2015-10-15 08:01:48 -0700288 const SkMatrix& inMatrix,
senorblanco1ea67a32016-01-19 08:50:18 -0800289 const SkIRect& bounds) const {
joshualittb0a8a372014-09-23 09:50:21 -0700290 if (fp) {
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000291 GrContext* context = texture->getContext();
bsalomonf2703d82014-10-28 14:33:06 -0700292 GrSurfaceDesc maskDesc;
bsalomon76228632015-05-29 08:02:10 -0700293 if (context->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000294 maskDesc.fConfig = kAlpha_8_GrPixelConfig;
295 } else {
296 maskDesc.fConfig = kRGBA_8888_GrPixelConfig;
297 }
bsalomon6bc1b5f2015-02-23 09:06:38 -0800298 maskDesc.fFlags = kRenderTarget_GrSurfaceFlag;
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000299 // Add one pixel of border to ensure that clamp mode will be all zeros
300 // the outside.
senorblanco1ea67a32016-01-19 08:50:18 -0800301 maskDesc.fWidth = bounds.width();
302 maskDesc.fHeight = bounds.height();
bsalomoneae62002015-07-31 13:59:30 -0700303 SkAutoTUnref<GrTexture> maskTexture(
304 context->textureProvider()->createApproxTexture(maskDesc));
bsalomone3059732014-10-14 11:47:22 -0700305 if (!maskTexture) {
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000306 return false;
307 }
308
robertphillips2e1e51f2015-10-15 08:01:48 -0700309 SkAutoTUnref<GrDrawContext> drawContext(
310 context->drawContext(maskTexture->asRenderTarget()));
robertphillipsea461502015-05-26 11:38:03 -0700311 if (drawContext) {
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000312 GrPaint grPaint;
egdaniel95131432014-12-09 11:15:43 -0800313 grPaint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000314 SkRegion::Iterator iter(fRegion);
robertphillips2e1e51f2015-10-15 08:01:48 -0700315 drawContext->clear(nullptr, 0x0, true);
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000316
senorblanco1ea67a32016-01-19 08:50:18 -0800317 GrClip clip(SkRect::Make(SkIRect::MakeWH(bounds.width(), bounds.height())));
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000318 while (!iter.done()) {
319 SkRect rect = SkRect::Make(iter.rect());
senorblanco1ea67a32016-01-19 08:50:18 -0800320 drawContext->drawRect(clip, grPaint, inMatrix, rect);
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000321 iter.next();
322 }
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000323 }
324
bsalomon4a339522015-10-06 08:40:50 -0700325 *fp = AlphaThresholdEffect::Create(texture,
joshualittb0a8a372014-09-23 09:50:21 -0700326 maskTexture,
327 fInnerThreshold,
senorblanco1ea67a32016-01-19 08:50:18 -0800328 fOuterThreshold,
329 bounds);
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000330 }
331 return true;
332}
333#endif
334
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +0000335void SkAlphaThresholdFilterImpl::flatten(SkWriteBuffer& buffer) const {
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000336 this->INHERITED::flatten(buffer);
337 buffer.writeScalar(fInnerThreshold);
338 buffer.writeScalar(fOuterThreshold);
339 buffer.writeRegion(fRegion);
340}
341
robertphillips48e78462016-02-17 13:57:16 -0800342bool SkAlphaThresholdFilterImpl::onFilterImageDeprecated(Proxy* proxy, const SkBitmap& src,
343 const Context& ctx, SkBitmap* dst,
344 SkIPoint* offset) const {
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000345
commit-bot@chromium.org28fcae22014-04-11 17:15:40 +0000346 if (src.colorType() != kN32_SkColorType) {
commit-bot@chromium.org9109e182014-01-07 16:04:01 +0000347 return false;
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000348 }
349
350 SkMatrix localInverse;
senorblanco@chromium.org4cb543d2014-03-14 15:44:01 +0000351 if (!ctx.ctm().invert(&localInverse)) {
commit-bot@chromium.org9109e182014-01-07 16:04:01 +0000352 return false;
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000353 }
354
355 SkAutoLockPixels alp(src);
356 SkASSERT(src.getPixels());
357 if (!src.getPixels() || src.width() <= 0 || src.height() <= 0) {
commit-bot@chromium.org9109e182014-01-07 16:04:01 +0000358 return false;
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000359 }
360
senorblanco1d3ff432015-10-20 10:17:34 -0700361 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(src.width(), src.height()));
362 if (!device) {
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000363 return false;
364 }
senorblanco1d3ff432015-10-20 10:17:34 -0700365 *dst = device->accessBitmap(false);
366 SkAutoLockPixels alp_dst(*dst);
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000367
commit-bot@chromium.org9109e182014-01-07 16:04:01 +0000368 U8CPU innerThreshold = (U8CPU)(fInnerThreshold * 0xFF);
369 U8CPU outerThreshold = (U8CPU)(fOuterThreshold * 0xFF);
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000370 SkColor* sptr = src.getAddr32(0, 0);
371 SkColor* dptr = dst->getAddr32(0, 0);
372 int width = src.width(), height = src.height();
373 for (int y = 0; y < height; ++y) {
374 for (int x = 0; x < width; ++x) {
375 const SkColor& source = sptr[y * width + x];
376 SkColor output_color(source);
377 SkPoint position;
commit-bot@chromium.org9109e182014-01-07 16:04:01 +0000378 localInverse.mapXY((SkScalar)x, (SkScalar)y, &position);
379 if (fRegion.contains((int32_t)position.x(), (int32_t)position.y())) {
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000380 if (SkColorGetA(source) < innerThreshold) {
381 U8CPU alpha = SkColorGetA(source);
382 if (alpha == 0)
383 alpha = 1;
384 float scale = (float)innerThreshold / alpha;
385 output_color = SkColorSetARGB(innerThreshold,
commit-bot@chromium.org9109e182014-01-07 16:04:01 +0000386 (U8CPU)(SkColorGetR(source) * scale),
387 (U8CPU)(SkColorGetG(source) * scale),
388 (U8CPU)(SkColorGetB(source) * scale));
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000389 }
390 } else {
391 if (SkColorGetA(source) > outerThreshold) {
392 float scale = (float)outerThreshold / SkColorGetA(source);
393 output_color = SkColorSetARGB(outerThreshold,
commit-bot@chromium.org9109e182014-01-07 16:04:01 +0000394 (U8CPU)(SkColorGetR(source) * scale),
395 (U8CPU)(SkColorGetG(source) * scale),
396 (U8CPU)(SkColorGetB(source) * scale));
commit-bot@chromium.org40eb3c12014-01-06 23:41:14 +0000397 }
398 }
399 dptr[y * dst->width() + x] = output_color;
400 }
401 }
402
403 return true;
404}
robertphillipsf3f5bad2014-12-19 13:49:15 -0800405
406#ifndef SK_IGNORE_TO_STRING
407void SkAlphaThresholdFilterImpl::toString(SkString* str) const {
408 str->appendf("SkAlphaThresholdImageFilter: (");
409 str->appendf("inner: %f outer: %f", fInnerThreshold, fOuterThreshold);
410 str->append(")");
411}
412#endif