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