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