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 23bool SkColorFilter::asColorMode(SkColor*, SkBlendMode*) const { 24 return false; 25} 26 27bool SkColorFilter::asColorMatrix(SkScalar matrix[20]) const { 28 return false; 29} 30 31bool SkColorFilter::asComponentTable(SkBitmap*) const { 32 return false; 33} 34 35#if SK_SUPPORT_GPU 36sk_sp<GrFragmentProcessor> SkColorFilter::asFragmentProcessor(GrContext*, SkColorSpace*) const { 37 return nullptr; 38} 39#endif 40 41bool SkColorFilter::appendStages(SkRasterPipeline* pipeline, 42 SkColorSpace* dst, 43 SkArenaAlloc* scratch, 44 bool shaderIsOpaque) const { 45 return this->onAppendStages(pipeline, dst, scratch, shaderIsOpaque); 46} 47 48bool SkColorFilter::onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*, bool) const { 49 return false; 50} 51 52void SkColorFilter::filterSpan4f(const SkPM4f src[], int count, SkPM4f result[]) const { 53 const int N = 128; 54 SkPMColor tmp[N]; 55 while (count > 0) { 56 int n = SkTMin(count, N); 57 for (int i = 0; i < n; ++i) { 58 tmp[i] = src[i].toPMColor(); 59 } 60 this->filterSpan(tmp, n, tmp); 61 for (int i = 0; i < n; ++i) { 62 result[i] = SkPM4f::FromPMColor(tmp[i]); 63 } 64 src += n; 65 result += n; 66 count -= n; 67 } 68} 69 70SkColor SkColorFilter::filterColor(SkColor c) const { 71 SkPMColor dst, src = SkPreMultiplyColor(c); 72 this->filterSpan(&src, 1, &dst); 73 return SkUnPreMultiply::PMColorToColor(dst); 74} 75 76SkColor4f SkColorFilter::filterColor4f(const SkColor4f& c) const { 77 SkPM4f dst, src = c.premul(); 78 this->filterSpan4f(&src, 1, &dst); 79 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 94class SkComposeColorFilter : public SkColorFilter { 95public: 96 uint32_t getFlags() const override { 97 // Can only claim alphaunchanged and SkPM4f support if both our proxys do. 98 return fOuter->getFlags() & fInner->getFlags(); 99 } 100 101 void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const override { 102 fInner->filterSpan(shader, count, result); 103 fOuter->filterSpan(result, count, result); 104 } 105 106 void filterSpan4f(const SkPM4f shader[], int count, SkPM4f result[]) const override { 107 fInner->filterSpan4f(shader, count, result); 108 fOuter->filterSpan4f(result, count, result); 109 } 110 111#ifndef SK_IGNORE_TO_STRING 112 void toString(SkString* str) const override { 113 SkString outerS, innerS; 114 fOuter->toString(&outerS); 115 fInner->toString(&innerS); 116 // These strings can be long. SkString::appendf has limitations. 117 str->append(SkStringPrintf("SkComposeColorFilter: outer(%s) inner(%s)", outerS.c_str(), 118 innerS.c_str())); 119 } 120#endif 121 122#if SK_SUPPORT_GPU 123 sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext* context, 124 SkColorSpace* dstColorSpace) const override { 125 sk_sp<GrFragmentProcessor> innerFP(fInner->asFragmentProcessor(context, dstColorSpace)); 126 sk_sp<GrFragmentProcessor> outerFP(fOuter->asFragmentProcessor(context, dstColorSpace)); 127 if (!innerFP || !outerFP) { 128 return nullptr; 129 } 130 sk_sp<GrFragmentProcessor> series[] = { std::move(innerFP), std::move(outerFP) }; 131 return GrFragmentProcessor::RunInSeries(series, 2); 132 } 133#endif 134 135 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposeColorFilter) 136 137protected: 138 void flatten(SkWriteBuffer& buffer) const override { 139 buffer.writeFlattenable(fOuter.get()); 140 buffer.writeFlattenable(fInner.get()); 141 } 142 143private: 144 SkComposeColorFilter(sk_sp<SkColorFilter> outer, sk_sp<SkColorFilter> inner, 145 int composedFilterCount) 146 : fOuter(std::move(outer)) 147 , fInner(std::move(inner)) 148 , fComposedFilterCount(composedFilterCount) 149 { 150 SkASSERT(composedFilterCount >= 2); 151 SkASSERT(composedFilterCount <= SK_MAX_COMPOSE_COLORFILTER_COUNT); 152 } 153 154 int privateComposedFilterCount() const override { 155 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 167sk_sp<SkFlattenable> SkComposeColorFilter::CreateProc(SkReadBuffer& buffer) { 168 sk_sp<SkColorFilter> outer(buffer.readColorFilter()); 169 sk_sp<SkColorFilter> inner(buffer.readColorFilter()); 170 return MakeComposeFilter(std::move(outer), std::move(inner)); 171} 172 173/////////////////////////////////////////////////////////////////////////////////////////////////// 174 175sk_sp<SkColorFilter> SkColorFilter::MakeComposeFilter(sk_sp<SkColorFilter> outer, 176 sk_sp<SkColorFilter> inner) { 177 if (!outer) { 178 return inner; 179 } 180 if (!inner) { 181 return outer; 182 } 183 184 // Give the subclass a shot at a more optimal composition... 185 auto composition = outer->makeComposed(inner); 186 if (composition) { 187 return composition; 188 } 189 190 int count = inner->privateComposedFilterCount() + outer->privateComposedFilterCount(); 191 if (count > SK_MAX_COMPOSE_COLORFILTER_COUNT) { 192 return nullptr; 193 } 194 return sk_sp<SkColorFilter>(new SkComposeColorFilter(std::move(outer), std::move(inner),count)); 195} 196 197#include "SkModeColorFilter.h" 198 199SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkColorFilter) 200SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkComposeColorFilter) 201SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkModeColorFilter) 202SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 203