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