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