1/* 2 * Copyright 2011 Google Inc. 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 "SkColorMatrixFilter.h" 9#include "SkColorSpace.h" 10#include "SkColorSpaceXformer.h" 11#if SK_SUPPORT_GPU 12 #include "GrFragmentProcessor.h" 13#endif 14 15static SkScalar byte_to_scale(U8CPU byte) { 16 if (0xFF == byte) { 17 // want to get this exact 18 return 1; 19 } else { 20 return byte * 0.00392156862745f; 21 } 22} 23 24// If we can't reduce to a mode filter in MakeLightingFilter(), this is the general case. 25// We operate as a matrix color filter, but remember our input colors in case we're asked 26// to onMakeColorSpace() a new filter. 27class SkLightingColorFilter : public SkColorFilter { 28public: 29 SkLightingColorFilter(SkColor mul, SkColor add) : fMul(mul), fAdd(add) { 30 SkColorMatrix matrix; 31 matrix.setScale(byte_to_scale(SkColorGetR(mul)), 32 byte_to_scale(SkColorGetG(mul)), 33 byte_to_scale(SkColorGetB(mul)), 34 1); 35 matrix.postTranslate(SkIntToScalar(SkColorGetR(add)), 36 SkIntToScalar(SkColorGetG(add)), 37 SkIntToScalar(SkColorGetB(add)), 38 0); 39 fMatrixFilter = SkColorFilter::MakeMatrixFilterRowMajor255(matrix.fMat); 40 } 41 42 // Overriding this method is the class' raison d'etre. 43 sk_sp<SkColorFilter> onMakeColorSpace(SkColorSpaceXformer* xformer) const override { 44 SkColor add = xformer->apply(fAdd); 45 if (add != fAdd) { 46 return sk_make_sp<SkLightingColorFilter>(fMul, add); 47 } 48 return this->INHERITED::onMakeColorSpace(xformer); 49 } 50 51 // Let fMatrixFilter handle all the other calls directly. 52 53 uint32_t getFlags() const override { 54 return fMatrixFilter->getFlags(); 55 } 56 bool asColorMatrix(SkScalar matrix[20]) const override { 57 return fMatrixFilter->asColorMatrix(matrix); 58 } 59 void onAppendStages(SkRasterPipeline* p, SkColorSpace* cs, SkArenaAlloc* alloc, 60 bool shaderIsOpaque) const override { 61 fMatrixFilter->appendStages(p, cs, alloc, shaderIsOpaque); 62 } 63 64 // TODO: might want to remember we're a lighting color filter through serialization? 65 void flatten(SkWriteBuffer& buf) const override { return fMatrixFilter->flatten(buf); } 66 Factory getFactory() const override { return fMatrixFilter->getFactory(); } 67 68#if SK_SUPPORT_GPU 69 std::unique_ptr<GrFragmentProcessor> asFragmentProcessor( 70 GrContext* ctx, const GrColorSpaceInfo& csi) const override { 71 return fMatrixFilter->asFragmentProcessor(ctx, csi); 72 } 73#endif 74 75#ifndef SK_IGNORE_TO_STRING 76 void toString(SkString* str) const override { fMatrixFilter->toString(str); } 77#endif 78 79private: 80 SkColor fMul, fAdd; 81 sk_sp<SkColorFilter> fMatrixFilter; 82 83 typedef SkColorFilter INHERITED; 84}; 85 86sk_sp<SkColorFilter> SkColorMatrixFilter::MakeLightingFilter(SkColor mul, SkColor add) { 87 const SkColor opaqueAlphaMask = SK_ColorBLACK; 88 // omit the alpha and compare only the RGB values 89 if (0 == (add & ~opaqueAlphaMask)) { 90 return SkColorFilter::MakeModeFilter(mul | opaqueAlphaMask, SkBlendMode::kModulate); 91 } 92 return sk_make_sp<SkLightingColorFilter>(mul, add); 93} 94