SkColorMatrixFilter.cpp revision 459c9679a221bbe66a735080728afb9599fa5ed7
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc. 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */ 7b67eb2f9b9ec097aa963245a85be13daec09d2ccreed 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorMatrixFilter.h" 9459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein#include "SkColorSpaceXformer.h" 10459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein#if SK_SUPPORT_GPU 11459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein #include "GrFragmentProcessor.h" 12459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein#endif 130daf5dd7fc682c939325e16cac6f8aa2e1295060reed 140daf5dd7fc682c939325e16cac6f8aa2e1295060reedstatic SkScalar byte_to_scale(U8CPU byte) { 150daf5dd7fc682c939325e16cac6f8aa2e1295060reed if (0xFF == byte) { 160daf5dd7fc682c939325e16cac6f8aa2e1295060reed // want to get this exact 170daf5dd7fc682c939325e16cac6f8aa2e1295060reed return 1; 180daf5dd7fc682c939325e16cac6f8aa2e1295060reed } else { 190daf5dd7fc682c939325e16cac6f8aa2e1295060reed return byte * 0.00392156862745f; 200daf5dd7fc682c939325e16cac6f8aa2e1295060reed } 210daf5dd7fc682c939325e16cac6f8aa2e1295060reed} 220daf5dd7fc682c939325e16cac6f8aa2e1295060reed 23459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein// If we can't reduce to a mode filter in MakeLightingFilter(), this is the general case. 24459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein// We operate as a matrix color filter, but remember our input colors in case we're asked 25459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein// to onMakeColorSpace() a new filter. 26459c9679a221bbe66a735080728afb9599fa5ed7Mike Kleinclass SkLightingColorFilter : public SkColorFilter { 27459c9679a221bbe66a735080728afb9599fa5ed7Mike Kleinpublic: 28459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein SkLightingColorFilter(SkColor mul, SkColor add) : fMul(mul), fAdd(add) { 29459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein SkColorMatrix matrix; 30459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein matrix.setScale(byte_to_scale(SkColorGetR(mul)), 31459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein byte_to_scale(SkColorGetG(mul)), 32459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein byte_to_scale(SkColorGetB(mul)), 33459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein 1); 34459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein matrix.postTranslate(SkIntToScalar(SkColorGetR(add)), 35459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein SkIntToScalar(SkColorGetG(add)), 36459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein SkIntToScalar(SkColorGetB(add)), 37459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein 0); 38459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein fMatrixFilter = SkColorFilter::MakeMatrixFilterRowMajor255(matrix.fMat); 39459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein } 40459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein 41459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein // Overriding this method is the class' raison d'etre. 42459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein sk_sp<SkColorFilter> onMakeColorSpace(SkColorSpaceXformer* xformer) const override { 43459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein return sk_make_sp<SkLightingColorFilter>(xformer->apply(fMul), xformer->apply(fAdd)); 44459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein } 45459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein 46459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein // Let fMatrixFilter handle all the other calls directly. 47459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein void filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const override { 48459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein fMatrixFilter->filterSpan(src, count, dst); 49459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein } 50459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein void filterSpan4f(const SkPM4f src[], int count, SkPM4f dst[]) const override { 51459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein fMatrixFilter->filterSpan4f(src, count, dst); 52459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein } 53459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein uint32_t getFlags() const override { 54459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein return fMatrixFilter->getFlags(); 55459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein } 56459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein bool asColorMatrix(SkScalar matrix[20]) const override { 57459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein return fMatrixFilter->asColorMatrix(matrix); 58459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein } 59459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein bool onAppendStages(SkRasterPipeline* p, SkColorSpace* cs, SkArenaAlloc* alloc, 60459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein bool shaderIsOpaque) const override { 61459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein return fMatrixFilter->appendStages(p, cs, alloc, shaderIsOpaque); 62459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein } 63459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein 64459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein // TODO: might want to remember we're a lighting color filter through serialization? 65459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein void flatten(SkWriteBuffer& buf) const override { return fMatrixFilter->flatten(buf); } 66459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein Factory getFactory() const override { return fMatrixFilter->getFactory(); } 67459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein 68459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein#if SK_SUPPORT_GPU 69459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext* ctx, 70459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein SkColorSpace* cs) const override { 71459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein return fMatrixFilter->asFragmentProcessor(ctx, cs); 72459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein } 73459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein#endif 74459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein 75459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein#ifndef SK_IGNORE_TO_STRING 76459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein void toString(SkString* str) const override { fMatrixFilter->toString(str); } 77459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein#endif 78459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein 79459c9679a221bbe66a735080728afb9599fa5ed7Mike Kleinprivate: 80459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein SkColor fMul, fAdd; 81459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein sk_sp<SkColorFilter> fMatrixFilter; 82459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein}; 83459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein 84d053ce9c54d4e5937a142278359e5a4cde18095ereedsk_sp<SkColorFilter> SkColorMatrixFilter::MakeLightingFilter(SkColor mul, SkColor add) { 850be0a3bb99549fc75a7d7229dd7ac2f62ec15cf9djsollen const SkColor opaqueAlphaMask = SK_ColorBLACK; 860be0a3bb99549fc75a7d7229dd7ac2f62ec15cf9djsollen // omit the alpha and compare only the RGB values 870be0a3bb99549fc75a7d7229dd7ac2f62ec15cf9djsollen if (0 == (add & ~opaqueAlphaMask)) { 887d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed return SkColorFilter::MakeModeFilter(mul | opaqueAlphaMask, SkBlendMode::kModulate); 890be0a3bb99549fc75a7d7229dd7ac2f62ec15cf9djsollen } 90459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein return sk_make_sp<SkLightingColorFilter>(mul, add); 910daf5dd7fc682c939325e16cac6f8aa2e1295060reed} 92