SkColorFilter.cpp revision 25f3805efa465bc3f804f192fe1ee64450f01d7c
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
8ac04fef619ad3939a25e66bdaef6f6b1e7f5ca50Herb Derby#include "SkArenaAlloc.h"
94e92b821f0396fe7ca1bd6498d0f044fb49e59c8Mike Klein#include "SkColorFilter.h"
104e92b821f0396fe7ca1bd6498d0f044fb49e59c8Mike Klein#include "SkColorSpaceXformer.h"
114e92b821f0396fe7ca1bd6498d0f044fb49e59c8Mike Klein#include "SkNx.h"
124e92b821f0396fe7ca1bd6498d0f044fb49e59c8Mike Klein#include "SkPM4f.h"
136dfcecad33c949e775a3fd0a58637721ab5e295eMike Klein#include "SkRasterPipeline.h"
148b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h"
15d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include "SkRefCnt.h"
165bd055c0386499f2dc8c66173a7534b75af602bfreed#include "SkString.h"
17d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include "SkTDArray.h"
18d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include "SkUnPreMultiply.h"
19db873d8677a2d4ecfe38a794a5d868301bdeeabereed#include "SkWriteBuffer.h"
206dfcecad33c949e775a3fd0a58637721ab5e295eMike Klein#include "../jumper/SkJumper.h"
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon#if SK_SUPPORT_GPU
23e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon#include "GrFragmentProcessor.h"
24e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon#endif
25d3ebb48320cf1b7e969974673e4bd7743816985ebungeman
26faba3715b8ddfaa0ce4df79bc8006e9bc7694e5bMike Reedbool SkColorFilter::asColorMode(SkColor*, SkBlendMode*) const {
2743c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    return false;
2843c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com}
2943c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com
30bada64428a52b4fc1f31a0a1982c2301ec57601creed@google.combool SkColorFilter::asColorMatrix(SkScalar matrix[20]) const {
31e5ff3cefe007d092daf9d0bc2b03f9ff87b2c34esenorblanco@chromium.org    return false;
32e5ff3cefe007d092daf9d0bc2b03f9ff87b2c34esenorblanco@chromium.org}
33e5ff3cefe007d092daf9d0bc2b03f9ff87b2c34esenorblanco@chromium.org
34b2ad101313cfba9c06a3a4dc06531766bcbec73bbsalomon@google.combool SkColorFilter::asComponentTable(SkBitmap*) const {
357191840eec5ac3b5f5814e4df3cf18264b0b0a4dreed@google.com    return false;
367191840eec5ac3b5f5814e4df3cf18264b0b0a4dreed@google.com}
377191840eec5ac3b5f5814e4df3cf18264b0b0a4dreed@google.com
3806ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman#if SK_SUPPORT_GPU
39618d304eb394d64779be0ecdc5eff898242faa8fBrian Osmansk_sp<GrFragmentProcessor> SkColorFilter::asFragmentProcessor(GrContext*, SkColorSpace*) const {
4006ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman    return nullptr;
4106ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman}
4206ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman#endif
4306ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman
446dfcecad33c949e775a3fd0a58637721ab5e295eMike Kleinvoid SkColorFilter::appendStages(SkRasterPipeline* p,
456dfcecad33c949e775a3fd0a58637721ab5e295eMike Klein                                 SkColorSpace* dstCS,
466dfcecad33c949e775a3fd0a58637721ab5e295eMike Klein                                 SkArenaAlloc* alloc,
47744908e5e81f81f34288a1b5547aa4ea990ad13dMike Klein                                 bool shaderIsOpaque) const {
48fdf31035a9639c2d377bdf2ddb404d269f8ca42aMike Klein    this->onAppendStages(p, dstCS, alloc, shaderIsOpaque);
49fdf31035a9639c2d377bdf2ddb404d269f8ca42aMike Klein}
506dfcecad33c949e775a3fd0a58637721ab5e295eMike Klein
51fdf31035a9639c2d377bdf2ddb404d269f8ca42aMike Kleinvoid SkColorFilter::onAppendStages(SkRasterPipeline* p,
52fdf31035a9639c2d377bdf2ddb404d269f8ca42aMike Klein                                   SkColorSpace* dstCS,
53fdf31035a9639c2d377bdf2ddb404d269f8ca42aMike Klein                                   SkArenaAlloc* alloc,
54fdf31035a9639c2d377bdf2ddb404d269f8ca42aMike Klein                                   bool) const {
556dfcecad33c949e775a3fd0a58637721ab5e295eMike Klein    struct Ctx : SkJumper_CallbackCtx {
566dfcecad33c949e775a3fd0a58637721ab5e295eMike Klein        sk_sp<SkColorFilter> cf;
576dfcecad33c949e775a3fd0a58637721ab5e295eMike Klein    };
586dfcecad33c949e775a3fd0a58637721ab5e295eMike Klein    auto ctx = alloc->make<Ctx>();
59b8fbab2a1c79764e490e65ebc80288cdc0494237Mike Klein    ctx->cf = dstCS ? SkColorSpaceXformer::Make(sk_ref_sp(dstCS))->apply(this)
60b8fbab2a1c79764e490e65ebc80288cdc0494237Mike Klein                    : sk_ref_sp(const_cast<SkColorFilter*>(this));
616dfcecad33c949e775a3fd0a58637721ab5e295eMike Klein    ctx->fn = [](SkJumper_CallbackCtx* arg, int active_pixels) {
626dfcecad33c949e775a3fd0a58637721ab5e295eMike Klein        auto ctx = (Ctx*)arg;
636dfcecad33c949e775a3fd0a58637721ab5e295eMike Klein        auto buf = (SkPM4f*)ctx->rgba;
6425f3805efa465bc3f804f192fe1ee64450f01d7cMike Reed        ctx->cf->onFilterStage(buf, active_pixels, buf);
656dfcecad33c949e775a3fd0a58637721ab5e295eMike Klein    };
666dfcecad33c949e775a3fd0a58637721ab5e295eMike Klein    p->append(SkRasterPipeline::callback, ctx);
679a5c47f4effba3b48a9a8c7c144b72b532d06efemtklein}
689a5c47f4effba3b48a9a8c7c144b72b532d06efemtklein
69bada64428a52b4fc1f31a0a1982c2301ec57601creed@google.comSkColor SkColorFilter::filterColor(SkColor c) const {
706b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com    SkPMColor dst, src = SkPreMultiplyColor(c);
716b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com    this->filterSpan(&src, 1, &dst);
726b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com    return SkUnPreMultiply::PMColorToColor(dst);
736b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com}
746b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com
7525f3805efa465bc3f804f192fe1ee64450f01d7cMike Reed#include "SkRasterPipeline.h"
76f7cdb06d62bd732599c7ee407dfd76d32d671755reedSkColor4f SkColorFilter::filterColor4f(const SkColor4f& c) const {
77f7cdb06d62bd732599c7ee407dfd76d32d671755reed    SkPM4f dst, src = c.premul();
7825f3805efa465bc3f804f192fe1ee64450f01d7cMike Reed
7925f3805efa465bc3f804f192fe1ee64450f01d7cMike Reed    SkSTArenaAlloc<128> alloc;
8025f3805efa465bc3f804f192fe1ee64450f01d7cMike Reed    SkRasterPipeline    pipeline(&alloc);
8125f3805efa465bc3f804f192fe1ee64450f01d7cMike Reed
8225f3805efa465bc3f804f192fe1ee64450f01d7cMike Reed    pipeline.append(SkRasterPipeline::constant_color, &src);
8325f3805efa465bc3f804f192fe1ee64450f01d7cMike Reed    this->onAppendStages(&pipeline, nullptr, &alloc, c.fA == 1);
8425f3805efa465bc3f804f192fe1ee64450f01d7cMike Reed    SkPM4f* dstPtr = &dst;
8525f3805efa465bc3f804f192fe1ee64450f01d7cMike Reed    pipeline.append(SkRasterPipeline::store_f32, &dstPtr);
8625f3805efa465bc3f804f192fe1ee64450f01d7cMike Reed    pipeline.run(0,1);
8725f3805efa465bc3f804f192fe1ee64450f01d7cMike Reed
88f7cdb06d62bd732599c7ee407dfd76d32d671755reed    return dst.unpremul();
896d3cef930ad19b0f55543ca40f7a07030f4fe508reed}
906d3cef930ad19b0f55543ca40f7a07030f4fe508reed
91db873d8677a2d4ecfe38a794a5d868301bdeeabereed///////////////////////////////////////////////////////////////////////////////////////////////////
92db873d8677a2d4ecfe38a794a5d868301bdeeabereed
93dc812222a7488d2a0e39b4a09c81c9f000d4b869reed/*
94dc812222a7488d2a0e39b4a09c81c9f000d4b869reed *  Since colorfilters may be used on the GPU backend, and in that case we may string together
95dc812222a7488d2a0e39b4a09c81c9f000d4b869reed *  many GrFragmentProcessors, we might exceed some internal instruction/resource limit.
96dc812222a7488d2a0e39b4a09c81c9f000d4b869reed *
97dc812222a7488d2a0e39b4a09c81c9f000d4b869reed *  Since we don't yet know *what* those limits might be when we construct the final shader,
98dc812222a7488d2a0e39b4a09c81c9f000d4b869reed *  we just set an arbitrary limit during construction. If later we find smarter ways to know what
99dc812222a7488d2a0e39b4a09c81c9f000d4b869reed *  the limnits are, we can change this constant (or remove it).
100dc812222a7488d2a0e39b4a09c81c9f000d4b869reed */
101dc812222a7488d2a0e39b4a09c81c9f000d4b869reed#define SK_MAX_COMPOSE_COLORFILTER_COUNT    4
102dc812222a7488d2a0e39b4a09c81c9f000d4b869reed
103db873d8677a2d4ecfe38a794a5d868301bdeeabereedclass SkComposeColorFilter : public SkColorFilter {
104db873d8677a2d4ecfe38a794a5d868301bdeeabereedpublic:
10536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    uint32_t getFlags() const override {
106f7cdb06d62bd732599c7ee407dfd76d32d671755reed        // Can only claim alphaunchanged and SkPM4f support if both our proxys do.
107db873d8677a2d4ecfe38a794a5d868301bdeeabereed        return fOuter->getFlags() & fInner->getFlags();
108db873d8677a2d4ecfe38a794a5d868301bdeeabereed    }
1099d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
11036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const override {
111db873d8677a2d4ecfe38a794a5d868301bdeeabereed        fInner->filterSpan(shader, count, result);
112db873d8677a2d4ecfe38a794a5d868301bdeeabereed        fOuter->filterSpan(result, count, result);
113db873d8677a2d4ecfe38a794a5d868301bdeeabereed    }
1149d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
115db873d8677a2d4ecfe38a794a5d868301bdeeabereed#ifndef SK_IGNORE_TO_STRING
11636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void toString(SkString* str) const override {
117db873d8677a2d4ecfe38a794a5d868301bdeeabereed        SkString outerS, innerS;
118db873d8677a2d4ecfe38a794a5d868301bdeeabereed        fOuter->toString(&outerS);
119db873d8677a2d4ecfe38a794a5d868301bdeeabereed        fInner->toString(&innerS);
12027bece831ddecfd33ee5fecd81ca9e6939b30e49Hal Canary        // These strings can be long.  SkString::appendf has limitations.
12127bece831ddecfd33ee5fecd81ca9e6939b30e49Hal Canary        str->append(SkStringPrintf("SkComposeColorFilter: outer(%s) inner(%s)", outerS.c_str(),
12227bece831ddecfd33ee5fecd81ca9e6939b30e49Hal Canary                                   innerS.c_str()));
123db873d8677a2d4ecfe38a794a5d868301bdeeabereed    }
124db873d8677a2d4ecfe38a794a5d868301bdeeabereed#endif
125db873d8677a2d4ecfe38a794a5d868301bdeeabereed
126fdf31035a9639c2d377bdf2ddb404d269f8ca42aMike Klein    void onAppendStages(SkRasterPipeline* p, SkColorSpace* dst, SkArenaAlloc* scratch,
1279444bdd32b4a3dcd1c5ac4099adade1b5ba167b7Mike Reed                        bool shaderIsOpaque) const override {
1289444bdd32b4a3dcd1c5ac4099adade1b5ba167b7Mike Reed        bool innerIsOpaque = shaderIsOpaque;
1299444bdd32b4a3dcd1c5ac4099adade1b5ba167b7Mike Reed        if (!(fInner->getFlags() & kAlphaUnchanged_Flag)) {
1309444bdd32b4a3dcd1c5ac4099adade1b5ba167b7Mike Reed            innerIsOpaque = false;
1319444bdd32b4a3dcd1c5ac4099adade1b5ba167b7Mike Reed        }
1326dfcecad33c949e775a3fd0a58637721ab5e295eMike Klein        fInner->appendStages(p, dst, scratch, shaderIsOpaque);
1336dfcecad33c949e775a3fd0a58637721ab5e295eMike Klein        fOuter->appendStages(p, dst, scratch, innerIsOpaque);
1349444bdd32b4a3dcd1c5ac4099adade1b5ba167b7Mike Reed    }
1359444bdd32b4a3dcd1c5ac4099adade1b5ba167b7Mike Reed
136db873d8677a2d4ecfe38a794a5d868301bdeeabereed#if SK_SUPPORT_GPU
137618d304eb394d64779be0ecdc5eff898242faa8fBrian Osman    sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext* context,
138618d304eb394d64779be0ecdc5eff898242faa8fBrian Osman                                                   SkColorSpace* dstColorSpace) const override {
139618d304eb394d64779be0ecdc5eff898242faa8fBrian Osman        sk_sp<GrFragmentProcessor> innerFP(fInner->asFragmentProcessor(context, dstColorSpace));
140618d304eb394d64779be0ecdc5eff898242faa8fBrian Osman        sk_sp<GrFragmentProcessor> outerFP(fOuter->asFragmentProcessor(context, dstColorSpace));
141e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon        if (!innerFP || !outerFP) {
142e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon            return nullptr;
143e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon        }
14406ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman        sk_sp<GrFragmentProcessor> series[] = { std::move(innerFP), std::move(outerFP) };
145e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon        return GrFragmentProcessor::RunInSeries(series, 2);
146cff10b21a9934afc540d121b493b204335829589reed    }
147db873d8677a2d4ecfe38a794a5d868301bdeeabereed#endif
148db873d8677a2d4ecfe38a794a5d868301bdeeabereed
149db873d8677a2d4ecfe38a794a5d868301bdeeabereed    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposeColorFilter)
1509d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
151db873d8677a2d4ecfe38a794a5d868301bdeeabereedprotected:
15236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void flatten(SkWriteBuffer& buffer) const override {
153d053ce9c54d4e5937a142278359e5a4cde18095ereed        buffer.writeFlattenable(fOuter.get());
154d053ce9c54d4e5937a142278359e5a4cde18095ereed        buffer.writeFlattenable(fInner.get());
155db873d8677a2d4ecfe38a794a5d868301bdeeabereed    }
1569d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
157db873d8677a2d4ecfe38a794a5d868301bdeeabereedprivate:
158d053ce9c54d4e5937a142278359e5a4cde18095ereed    SkComposeColorFilter(sk_sp<SkColorFilter> outer, sk_sp<SkColorFilter> inner,
159d053ce9c54d4e5937a142278359e5a4cde18095ereed                         int composedFilterCount)
160d053ce9c54d4e5937a142278359e5a4cde18095ereed        : fOuter(std::move(outer))
161d053ce9c54d4e5937a142278359e5a4cde18095ereed        , fInner(std::move(inner))
162dc812222a7488d2a0e39b4a09c81c9f000d4b869reed        , fComposedFilterCount(composedFilterCount)
163dc812222a7488d2a0e39b4a09c81c9f000d4b869reed    {
164dc812222a7488d2a0e39b4a09c81c9f000d4b869reed        SkASSERT(composedFilterCount >= 2);
165dc812222a7488d2a0e39b4a09c81c9f000d4b869reed        SkASSERT(composedFilterCount <= SK_MAX_COMPOSE_COLORFILTER_COUNT);
166dc812222a7488d2a0e39b4a09c81c9f000d4b869reed    }
167dc812222a7488d2a0e39b4a09c81c9f000d4b869reed
16836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    int privateComposedFilterCount() const override {
169dc812222a7488d2a0e39b4a09c81c9f000d4b869reed        return fComposedFilterCount;
170dc812222a7488d2a0e39b4a09c81c9f000d4b869reed    }
171dc812222a7488d2a0e39b4a09c81c9f000d4b869reed
172c1b879f11b937142f5478bd3b416b26be93dea23Matt Sarett    bool asACompose(SkColorFilter** outer, SkColorFilter** inner) const override {
173c1b879f11b937142f5478bd3b416b26be93dea23Matt Sarett        *outer = fOuter.get();
174c1b879f11b937142f5478bd3b416b26be93dea23Matt Sarett        *inner = fInner.get();
175c1b879f11b937142f5478bd3b416b26be93dea23Matt Sarett        return true;
176c1b879f11b937142f5478bd3b416b26be93dea23Matt Sarett    }
177c1b879f11b937142f5478bd3b416b26be93dea23Matt Sarett
1784e92b821f0396fe7ca1bd6498d0f044fb49e59c8Mike Klein    sk_sp<SkColorFilter> onMakeColorSpace(SkColorSpaceXformer* xformer) const override {
1794e92b821f0396fe7ca1bd6498d0f044fb49e59c8Mike Klein        return SkColorFilter::MakeComposeFilter(xformer->apply(fOuter.get()),
1804e92b821f0396fe7ca1bd6498d0f044fb49e59c8Mike Klein                                                xformer->apply(fInner.get()));
1814e92b821f0396fe7ca1bd6498d0f044fb49e59c8Mike Klein    }
1824e92b821f0396fe7ca1bd6498d0f044fb49e59c8Mike Klein
183d053ce9c54d4e5937a142278359e5a4cde18095ereed    sk_sp<SkColorFilter> fOuter;
184d053ce9c54d4e5937a142278359e5a4cde18095ereed    sk_sp<SkColorFilter> fInner;
185d053ce9c54d4e5937a142278359e5a4cde18095ereed    const int            fComposedFilterCount;
186db873d8677a2d4ecfe38a794a5d868301bdeeabereed
187db873d8677a2d4ecfe38a794a5d868301bdeeabereed    friend class SkColorFilter;
188db873d8677a2d4ecfe38a794a5d868301bdeeabereed
189db873d8677a2d4ecfe38a794a5d868301bdeeabereed    typedef SkColorFilter INHERITED;
190db873d8677a2d4ecfe38a794a5d868301bdeeabereed};
191db873d8677a2d4ecfe38a794a5d868301bdeeabereed
19260c9b58b3214b0154c931656e91e39b230e987d8reedsk_sp<SkFlattenable> SkComposeColorFilter::CreateProc(SkReadBuffer& buffer) {
193d053ce9c54d4e5937a142278359e5a4cde18095ereed    sk_sp<SkColorFilter> outer(buffer.readColorFilter());
194d053ce9c54d4e5937a142278359e5a4cde18095ereed    sk_sp<SkColorFilter> inner(buffer.readColorFilter());
19560c9b58b3214b0154c931656e91e39b230e987d8reed    return MakeComposeFilter(std::move(outer), std::move(inner));
196db873d8677a2d4ecfe38a794a5d868301bdeeabereed}
197db873d8677a2d4ecfe38a794a5d868301bdeeabereed
1988a8d841d485ff36b64d838575eb3735c1ddcf929reed///////////////////////////////////////////////////////////////////////////////////////////////////
1998a8d841d485ff36b64d838575eb3735c1ddcf929reed
200d053ce9c54d4e5937a142278359e5a4cde18095ereedsk_sp<SkColorFilter> SkColorFilter::MakeComposeFilter(sk_sp<SkColorFilter> outer,
201d053ce9c54d4e5937a142278359e5a4cde18095ereed                                                      sk_sp<SkColorFilter> inner) {
202db873d8677a2d4ecfe38a794a5d868301bdeeabereed    if (!outer) {
203d053ce9c54d4e5937a142278359e5a4cde18095ereed        return inner;
204db873d8677a2d4ecfe38a794a5d868301bdeeabereed    }
205db873d8677a2d4ecfe38a794a5d868301bdeeabereed    if (!inner) {
206d053ce9c54d4e5937a142278359e5a4cde18095ereed        return outer;
207db873d8677a2d4ecfe38a794a5d868301bdeeabereed    }
2088a8d841d485ff36b64d838575eb3735c1ddcf929reed
2098a8d841d485ff36b64d838575eb3735c1ddcf929reed    // Give the subclass a shot at a more optimal composition...
210d053ce9c54d4e5937a142278359e5a4cde18095ereed    auto composition = outer->makeComposed(inner);
211dc812222a7488d2a0e39b4a09c81c9f000d4b869reed    if (composition) {
212dc812222a7488d2a0e39b4a09c81c9f000d4b869reed        return composition;
213dc812222a7488d2a0e39b4a09c81c9f000d4b869reed    }
214dc812222a7488d2a0e39b4a09c81c9f000d4b869reed
215dc812222a7488d2a0e39b4a09c81c9f000d4b869reed    int count = inner->privateComposedFilterCount() + outer->privateComposedFilterCount();
216dc812222a7488d2a0e39b4a09c81c9f000d4b869reed    if (count > SK_MAX_COMPOSE_COLORFILTER_COUNT) {
21796fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
2188a8d841d485ff36b64d838575eb3735c1ddcf929reed    }
219d053ce9c54d4e5937a142278359e5a4cde18095ereed    return sk_sp<SkColorFilter>(new SkComposeColorFilter(std::move(outer), std::move(inner),count));
220db873d8677a2d4ecfe38a794a5d868301bdeeabereed}
221db873d8677a2d4ecfe38a794a5d868301bdeeabereed
222c7141eb8fba41f1e098499ef17d0bc79641d54c5reed#include "SkModeColorFilter.h"
223c7141eb8fba41f1e098499ef17d0bc79641d54c5reed
224db873d8677a2d4ecfe38a794a5d868301bdeeabereedSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkColorFilter)
225db873d8677a2d4ecfe38a794a5d868301bdeeabereedSK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkComposeColorFilter)
226c7141eb8fba41f1e098499ef17d0bc79641d54c5reedSK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkModeColorFilter)
227db873d8677a2d4ecfe38a794a5d868301bdeeabereedSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
228