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" 939e085559ddbd088866abdf50a48f7ab5b283830Florin Malita#include "SkColorSpace.h" 10459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein#include "SkColorSpaceXformer.h" 11459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein#if SK_SUPPORT_GPU 12459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein #include "GrFragmentProcessor.h" 13459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein#endif 140daf5dd7fc682c939325e16cac6f8aa2e1295060reed 150daf5dd7fc682c939325e16cac6f8aa2e1295060reedstatic SkScalar byte_to_scale(U8CPU byte) { 160daf5dd7fc682c939325e16cac6f8aa2e1295060reed if (0xFF == byte) { 170daf5dd7fc682c939325e16cac6f8aa2e1295060reed // want to get this exact 180daf5dd7fc682c939325e16cac6f8aa2e1295060reed return 1; 190daf5dd7fc682c939325e16cac6f8aa2e1295060reed } else { 200daf5dd7fc682c939325e16cac6f8aa2e1295060reed return byte * 0.00392156862745f; 210daf5dd7fc682c939325e16cac6f8aa2e1295060reed } 220daf5dd7fc682c939325e16cac6f8aa2e1295060reed} 230daf5dd7fc682c939325e16cac6f8aa2e1295060reed 24459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein// If we can't reduce to a mode filter in MakeLightingFilter(), this is the general case. 25459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein// We operate as a matrix color filter, but remember our input colors in case we're asked 26459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein// to onMakeColorSpace() a new filter. 27459c9679a221bbe66a735080728afb9599fa5ed7Mike Kleinclass SkLightingColorFilter : public SkColorFilter { 28459c9679a221bbe66a735080728afb9599fa5ed7Mike Kleinpublic: 29459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein SkLightingColorFilter(SkColor mul, SkColor add) : fMul(mul), fAdd(add) { 30459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein SkColorMatrix matrix; 31459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein matrix.setScale(byte_to_scale(SkColorGetR(mul)), 32459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein byte_to_scale(SkColorGetG(mul)), 33459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein byte_to_scale(SkColorGetB(mul)), 34459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein 1); 35459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein matrix.postTranslate(SkIntToScalar(SkColorGetR(add)), 36459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein SkIntToScalar(SkColorGetG(add)), 37459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein SkIntToScalar(SkColorGetB(add)), 38459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein 0); 39459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein fMatrixFilter = SkColorFilter::MakeMatrixFilterRowMajor255(matrix.fMat); 40459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein } 41459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein 42459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein // Overriding this method is the class' raison d'etre. 43459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein sk_sp<SkColorFilter> onMakeColorSpace(SkColorSpaceXformer* xformer) const override { 446d9f42984d94a2e9116dd951d47cd65cd8f4d401Mike Reed SkColor add = xformer->apply(fAdd); 456d9f42984d94a2e9116dd951d47cd65cd8f4d401Mike Reed if (add != fAdd) { 466d9f42984d94a2e9116dd951d47cd65cd8f4d401Mike Reed return sk_make_sp<SkLightingColorFilter>(fMul, add); 476d9f42984d94a2e9116dd951d47cd65cd8f4d401Mike Reed } 486d9f42984d94a2e9116dd951d47cd65cd8f4d401Mike Reed return this->INHERITED::onMakeColorSpace(xformer); 49459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein } 50459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein 51459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein // Let fMatrixFilter handle all the other calls directly. 529c1d7802284bf5a0e6fcf1a43e9218e21ce1a9e0Mike Reed 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 } 59fdf31035a9639c2d377bdf2ddb404d269f8ca42aMike Klein void onAppendStages(SkRasterPipeline* p, SkColorSpace* cs, SkArenaAlloc* alloc, 60459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein bool shaderIsOpaque) const override { 616dfcecad33c949e775a3fd0a58637721ab5e295eMike Klein 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; 826d9f42984d94a2e9116dd951d47cd65cd8f4d401Mike Reed 836d9f42984d94a2e9116dd951d47cd65cd8f4d401Mike Reed typedef SkColorFilter INHERITED; 84459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein}; 85459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein 86d053ce9c54d4e5937a142278359e5a4cde18095ereedsk_sp<SkColorFilter> SkColorMatrixFilter::MakeLightingFilter(SkColor mul, SkColor add) { 870be0a3bb99549fc75a7d7229dd7ac2f62ec15cf9djsollen const SkColor opaqueAlphaMask = SK_ColorBLACK; 880be0a3bb99549fc75a7d7229dd7ac2f62ec15cf9djsollen // omit the alpha and compare only the RGB values 890be0a3bb99549fc75a7d7229dd7ac2f62ec15cf9djsollen if (0 == (add & ~opaqueAlphaMask)) { 907d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed return SkColorFilter::MakeModeFilter(mul | opaqueAlphaMask, SkBlendMode::kModulate); 910be0a3bb99549fc75a7d7229dd7ac2f62ec15cf9djsollen } 92459c9679a221bbe66a735080728afb9599fa5ed7Mike Klein return sk_make_sp<SkLightingColorFilter>(mul, add); 930daf5dd7fc682c939325e16cac6f8aa2e1295060reed} 94