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