SkColorFilter.cpp revision d6889293dd0942f27f9593f679722c956831f2c4
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); 118 buffer.writeFlattenable(fInner); 119 } 120 121private: 122 SkComposeColorFilter(SkColorFilter* outer, SkColorFilter* inner, int composedFilterCount) 123 : fOuter(SkRef(outer)) 124 , fInner(SkRef(inner)) 125 , fComposedFilterCount(composedFilterCount) 126 { 127 SkASSERT(composedFilterCount >= 2); 128 SkASSERT(composedFilterCount <= SK_MAX_COMPOSE_COLORFILTER_COUNT); 129 } 130 131 int privateComposedFilterCount() const override { 132 return fComposedFilterCount; 133 } 134 135 SkAutoTUnref<SkColorFilter> fOuter; 136 SkAutoTUnref<SkColorFilter> fInner; 137 const int fComposedFilterCount; 138 139 friend class SkColorFilter; 140 141 typedef SkColorFilter INHERITED; 142}; 143 144SkFlattenable* SkComposeColorFilter::CreateProc(SkReadBuffer& buffer) { 145 SkAutoTUnref<SkColorFilter> outer(buffer.readColorFilter()); 146 SkAutoTUnref<SkColorFilter> inner(buffer.readColorFilter()); 147 return CreateComposeFilter(outer, inner); 148} 149 150/////////////////////////////////////////////////////////////////////////////////////////////////// 151 152SkColorFilter* SkColorFilter::CreateComposeFilter(SkColorFilter* outer, SkColorFilter* inner) { 153 if (!outer) { 154 return SkSafeRef(inner); 155 } 156 if (!inner) { 157 return SkSafeRef(outer); 158 } 159 160 // Give the subclass a shot at a more optimal composition... 161 SkColorFilter* composition = outer->newComposed(inner); 162 if (composition) { 163 return composition; 164 } 165 166 int count = inner->privateComposedFilterCount() + outer->privateComposedFilterCount(); 167 if (count > SK_MAX_COMPOSE_COLORFILTER_COUNT) { 168 return nullptr; 169 } 170 return new SkComposeColorFilter(outer, inner, count); 171} 172 173#include "SkModeColorFilter.h" 174 175SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkColorFilter) 176SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkComposeColorFilter) 177SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkModeColorFilter) 178SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 179 180