SkColorFilter.cpp revision b9641bd55a8f63757a63d9302755feb55d2e9502
1/*
2 * Copyright 2006 The Android Open Source Project
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 "SkArenaAlloc.h"
9#include "SkColorFilter.h"
10#include "SkColorSpaceXformer.h"
11#include "SkNx.h"
12#include "SkPM4f.h"
13#include "SkReadBuffer.h"
14#include "SkRefCnt.h"
15#include "SkString.h"
16#include "SkTDArray.h"
17#include "SkUnPreMultiply.h"
18#include "SkWriteBuffer.h"
19
20#if SK_SUPPORT_GPU
21#include "GrFragmentProcessor.h"
22#endif
23
24bool SkColorFilter::asColorMode(SkColor*, SkBlendMode*) const {
25    return false;
26}
27
28bool SkColorFilter::asColorMatrix(SkScalar matrix[20]) const {
29    return false;
30}
31
32bool SkColorFilter::asComponentTable(SkBitmap*) const {
33    return false;
34}
35
36#if SK_SUPPORT_GPU
37sk_sp<GrFragmentProcessor> SkColorFilter::asFragmentProcessor(GrContext*, SkColorSpace*) const {
38    return nullptr;
39}
40#endif
41
42bool SkColorFilter::appendStages(SkRasterPipeline* pipeline,
43                                 SkColorSpace* dst,
44                                 SkArenaAlloc* scratch,
45                                 bool shaderIsOpaque) const {
46    return this->onAppendStages(pipeline, dst, scratch, shaderIsOpaque);
47}
48
49bool SkColorFilter::onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*, bool) const {
50    return false;
51}
52
53SkColor SkColorFilter::filterColor(SkColor c) const {
54    SkPMColor dst, src = SkPreMultiplyColor(c);
55    this->filterSpan(&src, 1, &dst);
56    return SkUnPreMultiply::PMColorToColor(dst);
57}
58
59SkColor4f SkColorFilter::filterColor4f(const SkColor4f& c) const {
60    SkPM4f dst, src = c.premul();
61    this->filterSpan4f(&src, 1, &dst);
62    return dst.unpremul();
63}
64
65///////////////////////////////////////////////////////////////////////////////////////////////////
66
67/*
68 *  Since colorfilters may be used on the GPU backend, and in that case we may string together
69 *  many GrFragmentProcessors, we might exceed some internal instruction/resource limit.
70 *
71 *  Since we don't yet know *what* those limits might be when we construct the final shader,
72 *  we just set an arbitrary limit during construction. If later we find smarter ways to know what
73 *  the limnits are, we can change this constant (or remove it).
74 */
75#define SK_MAX_COMPOSE_COLORFILTER_COUNT    4
76
77class SkComposeColorFilter : public SkColorFilter {
78public:
79    uint32_t getFlags() const override {
80        // Can only claim alphaunchanged and SkPM4f support if both our proxys do.
81        return fOuter->getFlags() & fInner->getFlags();
82    }
83
84    void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const override {
85        fInner->filterSpan(shader, count, result);
86        fOuter->filterSpan(result, count, result);
87    }
88
89    void filterSpan4f(const SkPM4f shader[], int count, SkPM4f result[]) const override {
90        fInner->filterSpan4f(shader, count, result);
91        fOuter->filterSpan4f(result, count, result);
92    }
93
94#ifndef SK_IGNORE_TO_STRING
95    void toString(SkString* str) const override {
96        SkString outerS, innerS;
97        fOuter->toString(&outerS);
98        fInner->toString(&innerS);
99        // These strings can be long.  SkString::appendf has limitations.
100        str->append(SkStringPrintf("SkComposeColorFilter: outer(%s) inner(%s)", outerS.c_str(),
101                                   innerS.c_str()));
102    }
103#endif
104
105#if SK_SUPPORT_GPU
106    sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext* context,
107                                                   SkColorSpace* dstColorSpace) const override {
108        sk_sp<GrFragmentProcessor> innerFP(fInner->asFragmentProcessor(context, dstColorSpace));
109        sk_sp<GrFragmentProcessor> outerFP(fOuter->asFragmentProcessor(context, dstColorSpace));
110        if (!innerFP || !outerFP) {
111            return nullptr;
112        }
113        sk_sp<GrFragmentProcessor> series[] = { std::move(innerFP), std::move(outerFP) };
114        return GrFragmentProcessor::RunInSeries(series, 2);
115    }
116#endif
117
118    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposeColorFilter)
119
120protected:
121    void flatten(SkWriteBuffer& buffer) const override {
122        buffer.writeFlattenable(fOuter.get());
123        buffer.writeFlattenable(fInner.get());
124    }
125
126private:
127    SkComposeColorFilter(sk_sp<SkColorFilter> outer, sk_sp<SkColorFilter> inner,
128                         int composedFilterCount)
129        : fOuter(std::move(outer))
130        , fInner(std::move(inner))
131        , fComposedFilterCount(composedFilterCount)
132    {
133        SkASSERT(composedFilterCount >= 2);
134        SkASSERT(composedFilterCount <= SK_MAX_COMPOSE_COLORFILTER_COUNT);
135    }
136
137    int privateComposedFilterCount() const override {
138        return fComposedFilterCount;
139    }
140
141    bool asACompose(SkColorFilter** outer, SkColorFilter** inner) const override {
142        *outer = fOuter.get();
143        *inner = fInner.get();
144        return true;
145    }
146
147    sk_sp<SkColorFilter> onMakeColorSpace(SkColorSpaceXformer* xformer) const override {
148        return SkColorFilter::MakeComposeFilter(xformer->apply(fOuter.get()),
149                                                xformer->apply(fInner.get()));
150    }
151
152    sk_sp<SkColorFilter> fOuter;
153    sk_sp<SkColorFilter> fInner;
154    const int            fComposedFilterCount;
155
156    friend class SkColorFilter;
157
158    typedef SkColorFilter INHERITED;
159};
160
161sk_sp<SkFlattenable> SkComposeColorFilter::CreateProc(SkReadBuffer& buffer) {
162    sk_sp<SkColorFilter> outer(buffer.readColorFilter());
163    sk_sp<SkColorFilter> inner(buffer.readColorFilter());
164    return MakeComposeFilter(std::move(outer), std::move(inner));
165}
166
167///////////////////////////////////////////////////////////////////////////////////////////////////
168
169sk_sp<SkColorFilter> SkColorFilter::MakeComposeFilter(sk_sp<SkColorFilter> outer,
170                                                      sk_sp<SkColorFilter> inner) {
171    if (!outer) {
172        return inner;
173    }
174    if (!inner) {
175        return outer;
176    }
177
178    // Give the subclass a shot at a more optimal composition...
179    auto composition = outer->makeComposed(inner);
180    if (composition) {
181        return composition;
182    }
183
184    int count = inner->privateComposedFilterCount() + outer->privateComposedFilterCount();
185    if (count > SK_MAX_COMPOSE_COLORFILTER_COUNT) {
186        return nullptr;
187    }
188    return sk_sp<SkColorFilter>(new SkComposeColorFilter(std::move(outer), std::move(inner),count));
189}
190
191#include "SkModeColorFilter.h"
192
193SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkColorFilter)
194SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkComposeColorFilter)
195SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkModeColorFilter)
196SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
197