/* * Copyright 2011 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "SkColorMatrixFilter.h" #include "SkColorSpace.h" #include "SkColorSpaceXformer.h" #if SK_SUPPORT_GPU #include "GrFragmentProcessor.h" #endif static SkScalar byte_to_scale(U8CPU byte) { if (0xFF == byte) { // want to get this exact return 1; } else { return byte * 0.00392156862745f; } } // If we can't reduce to a mode filter in MakeLightingFilter(), this is the general case. // We operate as a matrix color filter, but remember our input colors in case we're asked // to onMakeColorSpace() a new filter. class SkLightingColorFilter : public SkColorFilter { public: SkLightingColorFilter(SkColor mul, SkColor add) : fMul(mul), fAdd(add) { SkColorMatrix matrix; matrix.setScale(byte_to_scale(SkColorGetR(mul)), byte_to_scale(SkColorGetG(mul)), byte_to_scale(SkColorGetB(mul)), 1); matrix.postTranslate(SkIntToScalar(SkColorGetR(add)), SkIntToScalar(SkColorGetG(add)), SkIntToScalar(SkColorGetB(add)), 0); fMatrixFilter = SkColorFilter::MakeMatrixFilterRowMajor255(matrix.fMat); } // Overriding this method is the class' raison d'etre. sk_sp onMakeColorSpace(SkColorSpaceXformer* xformer) const override { SkColor add = xformer->apply(fAdd); if (add != fAdd) { return sk_make_sp(fMul, add); } return this->INHERITED::onMakeColorSpace(xformer); } // Let fMatrixFilter handle all the other calls directly. uint32_t getFlags() const override { return fMatrixFilter->getFlags(); } bool asColorMatrix(SkScalar matrix[20]) const override { return fMatrixFilter->asColorMatrix(matrix); } void onAppendStages(SkRasterPipeline* p, SkColorSpace* cs, SkArenaAlloc* alloc, bool shaderIsOpaque) const override { fMatrixFilter->appendStages(p, cs, alloc, shaderIsOpaque); } // TODO: might want to remember we're a lighting color filter through serialization? void flatten(SkWriteBuffer& buf) const override { return fMatrixFilter->flatten(buf); } Factory getFactory() const override { return fMatrixFilter->getFactory(); } #if SK_SUPPORT_GPU std::unique_ptr asFragmentProcessor( GrContext* ctx, const GrColorSpaceInfo& csi) const override { return fMatrixFilter->asFragmentProcessor(ctx, csi); } #endif private: SkColor fMul, fAdd; sk_sp fMatrixFilter; typedef SkColorFilter INHERITED; }; sk_sp SkColorMatrixFilter::MakeLightingFilter(SkColor mul, SkColor add) { const SkColor opaqueAlphaMask = SK_ColorBLACK; // omit the alpha and compare only the RGB values if (0 == (add & ~opaqueAlphaMask)) { return SkColorFilter::MakeModeFilter(mul | opaqueAlphaMask, SkBlendMode::kModulate); } return sk_make_sp(mul, add); }