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