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