| /* |
| * Copyright 2006 The Android Open Source Project |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "SkColorFilter.h" |
| #include "SkReadBuffer.h" |
| #include "SkString.h" |
| #include "SkWriteBuffer.h" |
| |
| bool SkColorFilter::asColorMode(SkColor* color, SkXfermode::Mode* mode) const { |
| return false; |
| } |
| |
| bool SkColorFilter::asColorMatrix(SkScalar matrix[20]) const { |
| return false; |
| } |
| |
| bool SkColorFilter::asComponentTable(SkBitmap*) const { |
| return false; |
| } |
| |
| SkColor SkColorFilter::filterColor(SkColor c) const { |
| SkPMColor dst, src = SkPreMultiplyColor(c); |
| this->filterSpan(&src, 1, &dst); |
| return SkUnPreMultiply::PMColorToColor(dst); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| /* |
| * Since colorfilters may be used on the GPU backend, and in that case we may string together |
| * many GrFragmentProcessors, we might exceed some internal instruction/resource limit. |
| * |
| * Since we don't yet know *what* those limits might be when we construct the final shader, |
| * we just set an arbitrary limit during construction. If later we find smarter ways to know what |
| * the limnits are, we can change this constant (or remove it). |
| */ |
| #define SK_MAX_COMPOSE_COLORFILTER_COUNT 4 |
| |
| class SkComposeColorFilter : public SkColorFilter { |
| public: |
| uint32_t getFlags() const override { |
| // Can only claim alphaunchanged and 16bit support if both our proxys do. |
| return fOuter->getFlags() & fInner->getFlags(); |
| } |
| |
| void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const override { |
| fInner->filterSpan(shader, count, result); |
| fOuter->filterSpan(result, count, result); |
| } |
| |
| #ifndef SK_IGNORE_TO_STRING |
| void toString(SkString* str) const override { |
| SkString outerS, innerS; |
| fOuter->toString(&outerS); |
| fInner->toString(&innerS); |
| str->appendf("SkComposeColorFilter: outer(%s) inner(%s)", outerS.c_str(), innerS.c_str()); |
| } |
| #endif |
| |
| #if SK_SUPPORT_GPU |
| bool asFragmentProcessors(GrContext* context, |
| SkTDArray<GrFragmentProcessor*>* array) const override { |
| bool hasFrags = fInner->asFragmentProcessors(context, array); |
| hasFrags |= fOuter->asFragmentProcessors(context, array); |
| return hasFrags; |
| } |
| #endif |
| |
| SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposeColorFilter) |
| |
| protected: |
| void flatten(SkWriteBuffer& buffer) const override { |
| buffer.writeFlattenable(fOuter); |
| buffer.writeFlattenable(fInner); |
| } |
| |
| private: |
| SkComposeColorFilter(SkColorFilter* outer, SkColorFilter* inner, int composedFilterCount) |
| : fOuter(SkRef(outer)) |
| , fInner(SkRef(inner)) |
| , fComposedFilterCount(composedFilterCount) |
| { |
| SkASSERT(composedFilterCount >= 2); |
| SkASSERT(composedFilterCount <= SK_MAX_COMPOSE_COLORFILTER_COUNT); |
| } |
| |
| int privateComposedFilterCount() const override { |
| return fComposedFilterCount; |
| } |
| |
| SkAutoTUnref<SkColorFilter> fOuter; |
| SkAutoTUnref<SkColorFilter> fInner; |
| const int fComposedFilterCount; |
| |
| friend class SkColorFilter; |
| |
| typedef SkColorFilter INHERITED; |
| }; |
| |
| SkFlattenable* SkComposeColorFilter::CreateProc(SkReadBuffer& buffer) { |
| SkAutoTUnref<SkColorFilter> outer(buffer.readColorFilter()); |
| SkAutoTUnref<SkColorFilter> inner(buffer.readColorFilter()); |
| return CreateComposeFilter(outer, inner); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| SkColorFilter* SkColorFilter::CreateComposeFilter(SkColorFilter* outer, SkColorFilter* inner) { |
| if (!outer) { |
| return SkSafeRef(inner); |
| } |
| if (!inner) { |
| return SkSafeRef(outer); |
| } |
| |
| // Give the subclass a shot at a more optimal composition... |
| SkColorFilter* composition = outer->newComposed(inner); |
| if (composition) { |
| return composition; |
| } |
| |
| int count = inner->privateComposedFilterCount() + outer->privateComposedFilterCount(); |
| if (count > SK_MAX_COMPOSE_COLORFILTER_COUNT) { |
| return NULL; |
| } |
| return SkNEW_ARGS(SkComposeColorFilter, (outer, inner, count)); |
| } |
| |
| SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkColorFilter) |
| SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkComposeColorFilter) |
| SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |
| |