1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
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 */
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorFilter.h"
9ac04fef619ad3939a25e66bdaef6f6b1e7f5ca50Herb Derby#include "SkArenaAlloc.h"
108b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h"
11d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include "SkRefCnt.h"
125bd055c0386499f2dc8c66173a7534b75af602bfreed#include "SkString.h"
13d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include "SkTDArray.h"
14d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include "SkUnPreMultiply.h"
15db873d8677a2d4ecfe38a794a5d868301bdeeabereed#include "SkWriteBuffer.h"
16dd9ffea9ce051a49dbc6544e6aa3cb68fe987f47reed#include "SkPM4f.h"
17c5b1228141bd26d4573552a00ebeb0b85a4768dfreed#include "SkNx.h"
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon#if SK_SUPPORT_GPU
20e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon#include "GrFragmentProcessor.h"
21e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon#endif
22d3ebb48320cf1b7e969974673e4bd7743816985ebungeman
23faba3715b8ddfaa0ce4df79bc8006e9bc7694e5bMike Reedbool SkColorFilter::asColorMode(SkColor*, SkBlendMode*) const {
2443c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    return false;
2543c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com}
2643c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com
27bada64428a52b4fc1f31a0a1982c2301ec57601creed@google.combool SkColorFilter::asColorMatrix(SkScalar matrix[20]) const {
28e5ff3cefe007d092daf9d0bc2b03f9ff87b2c34esenorblanco@chromium.org    return false;
29e5ff3cefe007d092daf9d0bc2b03f9ff87b2c34esenorblanco@chromium.org}
30e5ff3cefe007d092daf9d0bc2b03f9ff87b2c34esenorblanco@chromium.org
31b2ad101313cfba9c06a3a4dc06531766bcbec73bbsalomon@google.combool SkColorFilter::asComponentTable(SkBitmap*) const {
327191840eec5ac3b5f5814e4df3cf18264b0b0a4dreed@google.com    return false;
337191840eec5ac3b5f5814e4df3cf18264b0b0a4dreed@google.com}
347191840eec5ac3b5f5814e4df3cf18264b0b0a4dreed@google.com
3506ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman#if SK_SUPPORT_GPU
36618d304eb394d64779be0ecdc5eff898242faa8fBrian Osmansk_sp<GrFragmentProcessor> SkColorFilter::asFragmentProcessor(GrContext*, SkColorSpace*) const {
3706ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman    return nullptr;
3806ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman}
3906ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman#endif
4006ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman
41744908e5e81f81f34288a1b5547aa4ea990ad13dMike Kleinbool SkColorFilter::appendStages(SkRasterPipeline* pipeline,
42744908e5e81f81f34288a1b5547aa4ea990ad13dMike Klein                                 SkColorSpace* dst,
43ac04fef619ad3939a25e66bdaef6f6b1e7f5ca50Herb Derby                                 SkArenaAlloc* scratch,
44744908e5e81f81f34288a1b5547aa4ea990ad13dMike Klein                                 bool shaderIsOpaque) const {
45744908e5e81f81f34288a1b5547aa4ea990ad13dMike Klein    return this->onAppendStages(pipeline, dst, scratch, shaderIsOpaque);
469a5c47f4effba3b48a9a8c7c144b72b532d06efemtklein}
479a5c47f4effba3b48a9a8c7c144b72b532d06efemtklein
48ac04fef619ad3939a25e66bdaef6f6b1e7f5ca50Herb Derbybool SkColorFilter::onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*, bool) const {
499a5c47f4effba3b48a9a8c7c144b72b532d06efemtklein    return false;
509a5c47f4effba3b48a9a8c7c144b72b532d06efemtklein}
519a5c47f4effba3b48a9a8c7c144b72b532d06efemtklein
52ff723af8b6bc7179132052fbab7d77ec2a20eba2brianosmanvoid SkColorFilter::filterSpan4f(const SkPM4f src[], int count, SkPM4f result[]) const {
53c5b1228141bd26d4573552a00ebeb0b85a4768dfreed    const int N = 128;
54c5b1228141bd26d4573552a00ebeb0b85a4768dfreed    SkPMColor tmp[N];
55c5b1228141bd26d4573552a00ebeb0b85a4768dfreed    while (count > 0) {
56c5b1228141bd26d4573552a00ebeb0b85a4768dfreed        int n = SkTMin(count, N);
57c5b1228141bd26d4573552a00ebeb0b85a4768dfreed        for (int i = 0; i < n; ++i) {
58e2cddc5342d5aacacce4429441c94d1e0ff67d8cbrianosman            tmp[i] = src[i].toPMColor();
59c5b1228141bd26d4573552a00ebeb0b85a4768dfreed        }
60c5b1228141bd26d4573552a00ebeb0b85a4768dfreed        this->filterSpan(tmp, n, tmp);
61c5b1228141bd26d4573552a00ebeb0b85a4768dfreed        for (int i = 0; i < n; ++i) {
62ff723af8b6bc7179132052fbab7d77ec2a20eba2brianosman            result[i] = SkPM4f::FromPMColor(tmp[i]);
63c5b1228141bd26d4573552a00ebeb0b85a4768dfreed        }
64ff723af8b6bc7179132052fbab7d77ec2a20eba2brianosman        src += n;
65ff723af8b6bc7179132052fbab7d77ec2a20eba2brianosman        result += n;
66c5b1228141bd26d4573552a00ebeb0b85a4768dfreed        count -= n;
67f7cdb06d62bd732599c7ee407dfd76d32d671755reed    }
68f7cdb06d62bd732599c7ee407dfd76d32d671755reed}
69f7cdb06d62bd732599c7ee407dfd76d32d671755reed
70bada64428a52b4fc1f31a0a1982c2301ec57601creed@google.comSkColor SkColorFilter::filterColor(SkColor c) const {
716b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com    SkPMColor dst, src = SkPreMultiplyColor(c);
726b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com    this->filterSpan(&src, 1, &dst);
736b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com    return SkUnPreMultiply::PMColorToColor(dst);
746b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com}
756b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com
76f7cdb06d62bd732599c7ee407dfd76d32d671755reedSkColor4f SkColorFilter::filterColor4f(const SkColor4f& c) const {
77f7cdb06d62bd732599c7ee407dfd76d32d671755reed    SkPM4f dst, src = c.premul();
78f7cdb06d62bd732599c7ee407dfd76d32d671755reed    this->filterSpan4f(&src, 1, &dst);
79f7cdb06d62bd732599c7ee407dfd76d32d671755reed    return dst.unpremul();
806d3cef930ad19b0f55543ca40f7a07030f4fe508reed}
816d3cef930ad19b0f55543ca40f7a07030f4fe508reed
82db873d8677a2d4ecfe38a794a5d868301bdeeabereed///////////////////////////////////////////////////////////////////////////////////////////////////
83db873d8677a2d4ecfe38a794a5d868301bdeeabereed
84dc812222a7488d2a0e39b4a09c81c9f000d4b869reed/*
85dc812222a7488d2a0e39b4a09c81c9f000d4b869reed *  Since colorfilters may be used on the GPU backend, and in that case we may string together
86dc812222a7488d2a0e39b4a09c81c9f000d4b869reed *  many GrFragmentProcessors, we might exceed some internal instruction/resource limit.
87dc812222a7488d2a0e39b4a09c81c9f000d4b869reed *
88dc812222a7488d2a0e39b4a09c81c9f000d4b869reed *  Since we don't yet know *what* those limits might be when we construct the final shader,
89dc812222a7488d2a0e39b4a09c81c9f000d4b869reed *  we just set an arbitrary limit during construction. If later we find smarter ways to know what
90dc812222a7488d2a0e39b4a09c81c9f000d4b869reed *  the limnits are, we can change this constant (or remove it).
91dc812222a7488d2a0e39b4a09c81c9f000d4b869reed */
92dc812222a7488d2a0e39b4a09c81c9f000d4b869reed#define SK_MAX_COMPOSE_COLORFILTER_COUNT    4
93dc812222a7488d2a0e39b4a09c81c9f000d4b869reed
94db873d8677a2d4ecfe38a794a5d868301bdeeabereedclass SkComposeColorFilter : public SkColorFilter {
95db873d8677a2d4ecfe38a794a5d868301bdeeabereedpublic:
9636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    uint32_t getFlags() const override {
97f7cdb06d62bd732599c7ee407dfd76d32d671755reed        // Can only claim alphaunchanged and SkPM4f support if both our proxys do.
98db873d8677a2d4ecfe38a794a5d868301bdeeabereed        return fOuter->getFlags() & fInner->getFlags();
99db873d8677a2d4ecfe38a794a5d868301bdeeabereed    }
1009d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
10136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const override {
102db873d8677a2d4ecfe38a794a5d868301bdeeabereed        fInner->filterSpan(shader, count, result);
103db873d8677a2d4ecfe38a794a5d868301bdeeabereed        fOuter->filterSpan(result, count, result);
104db873d8677a2d4ecfe38a794a5d868301bdeeabereed    }
1059d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
106f7cdb06d62bd732599c7ee407dfd76d32d671755reed    void filterSpan4f(const SkPM4f shader[], int count, SkPM4f result[]) const override {
107f7cdb06d62bd732599c7ee407dfd76d32d671755reed        fInner->filterSpan4f(shader, count, result);
108f7cdb06d62bd732599c7ee407dfd76d32d671755reed        fOuter->filterSpan4f(result, count, result);
109f7cdb06d62bd732599c7ee407dfd76d32d671755reed    }
1109d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
111db873d8677a2d4ecfe38a794a5d868301bdeeabereed#ifndef SK_IGNORE_TO_STRING
11236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void toString(SkString* str) const override {
113db873d8677a2d4ecfe38a794a5d868301bdeeabereed        SkString outerS, innerS;
114db873d8677a2d4ecfe38a794a5d868301bdeeabereed        fOuter->toString(&outerS);
115db873d8677a2d4ecfe38a794a5d868301bdeeabereed        fInner->toString(&innerS);
11627bece831ddecfd33ee5fecd81ca9e6939b30e49Hal Canary        // These strings can be long.  SkString::appendf has limitations.
11727bece831ddecfd33ee5fecd81ca9e6939b30e49Hal Canary        str->append(SkStringPrintf("SkComposeColorFilter: outer(%s) inner(%s)", outerS.c_str(),
11827bece831ddecfd33ee5fecd81ca9e6939b30e49Hal Canary                                   innerS.c_str()));
119db873d8677a2d4ecfe38a794a5d868301bdeeabereed    }
120db873d8677a2d4ecfe38a794a5d868301bdeeabereed#endif
121db873d8677a2d4ecfe38a794a5d868301bdeeabereed
122db873d8677a2d4ecfe38a794a5d868301bdeeabereed#if SK_SUPPORT_GPU
123618d304eb394d64779be0ecdc5eff898242faa8fBrian Osman    sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext* context,
124618d304eb394d64779be0ecdc5eff898242faa8fBrian Osman                                                   SkColorSpace* dstColorSpace) const override {
125618d304eb394d64779be0ecdc5eff898242faa8fBrian Osman        sk_sp<GrFragmentProcessor> innerFP(fInner->asFragmentProcessor(context, dstColorSpace));
126618d304eb394d64779be0ecdc5eff898242faa8fBrian Osman        sk_sp<GrFragmentProcessor> outerFP(fOuter->asFragmentProcessor(context, dstColorSpace));
127e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon        if (!innerFP || !outerFP) {
128e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon            return nullptr;
129e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon        }
13006ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman        sk_sp<GrFragmentProcessor> series[] = { std::move(innerFP), std::move(outerFP) };
131e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon        return GrFragmentProcessor::RunInSeries(series, 2);
132cff10b21a9934afc540d121b493b204335829589reed    }
133db873d8677a2d4ecfe38a794a5d868301bdeeabereed#endif
134db873d8677a2d4ecfe38a794a5d868301bdeeabereed
135db873d8677a2d4ecfe38a794a5d868301bdeeabereed    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposeColorFilter)
1369d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
137db873d8677a2d4ecfe38a794a5d868301bdeeabereedprotected:
13836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void flatten(SkWriteBuffer& buffer) const override {
139d053ce9c54d4e5937a142278359e5a4cde18095ereed        buffer.writeFlattenable(fOuter.get());
140d053ce9c54d4e5937a142278359e5a4cde18095ereed        buffer.writeFlattenable(fInner.get());
141db873d8677a2d4ecfe38a794a5d868301bdeeabereed    }
1429d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
143db873d8677a2d4ecfe38a794a5d868301bdeeabereedprivate:
144d053ce9c54d4e5937a142278359e5a4cde18095ereed    SkComposeColorFilter(sk_sp<SkColorFilter> outer, sk_sp<SkColorFilter> inner,
145d053ce9c54d4e5937a142278359e5a4cde18095ereed                         int composedFilterCount)
146d053ce9c54d4e5937a142278359e5a4cde18095ereed        : fOuter(std::move(outer))
147d053ce9c54d4e5937a142278359e5a4cde18095ereed        , fInner(std::move(inner))
148dc812222a7488d2a0e39b4a09c81c9f000d4b869reed        , fComposedFilterCount(composedFilterCount)
149dc812222a7488d2a0e39b4a09c81c9f000d4b869reed    {
150dc812222a7488d2a0e39b4a09c81c9f000d4b869reed        SkASSERT(composedFilterCount >= 2);
151dc812222a7488d2a0e39b4a09c81c9f000d4b869reed        SkASSERT(composedFilterCount <= SK_MAX_COMPOSE_COLORFILTER_COUNT);
152dc812222a7488d2a0e39b4a09c81c9f000d4b869reed    }
153dc812222a7488d2a0e39b4a09c81c9f000d4b869reed
15436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    int privateComposedFilterCount() const override {
155dc812222a7488d2a0e39b4a09c81c9f000d4b869reed        return fComposedFilterCount;
156dc812222a7488d2a0e39b4a09c81c9f000d4b869reed    }
157dc812222a7488d2a0e39b4a09c81c9f000d4b869reed
158d053ce9c54d4e5937a142278359e5a4cde18095ereed    sk_sp<SkColorFilter> fOuter;
159d053ce9c54d4e5937a142278359e5a4cde18095ereed    sk_sp<SkColorFilter> fInner;
160d053ce9c54d4e5937a142278359e5a4cde18095ereed    const int            fComposedFilterCount;
161db873d8677a2d4ecfe38a794a5d868301bdeeabereed
162db873d8677a2d4ecfe38a794a5d868301bdeeabereed    friend class SkColorFilter;
163db873d8677a2d4ecfe38a794a5d868301bdeeabereed
164db873d8677a2d4ecfe38a794a5d868301bdeeabereed    typedef SkColorFilter INHERITED;
165db873d8677a2d4ecfe38a794a5d868301bdeeabereed};
166db873d8677a2d4ecfe38a794a5d868301bdeeabereed
16760c9b58b3214b0154c931656e91e39b230e987d8reedsk_sp<SkFlattenable> SkComposeColorFilter::CreateProc(SkReadBuffer& buffer) {
168d053ce9c54d4e5937a142278359e5a4cde18095ereed    sk_sp<SkColorFilter> outer(buffer.readColorFilter());
169d053ce9c54d4e5937a142278359e5a4cde18095ereed    sk_sp<SkColorFilter> inner(buffer.readColorFilter());
17060c9b58b3214b0154c931656e91e39b230e987d8reed    return MakeComposeFilter(std::move(outer), std::move(inner));
171db873d8677a2d4ecfe38a794a5d868301bdeeabereed}
172db873d8677a2d4ecfe38a794a5d868301bdeeabereed
1738a8d841d485ff36b64d838575eb3735c1ddcf929reed///////////////////////////////////////////////////////////////////////////////////////////////////
1748a8d841d485ff36b64d838575eb3735c1ddcf929reed
175d053ce9c54d4e5937a142278359e5a4cde18095ereedsk_sp<SkColorFilter> SkColorFilter::MakeComposeFilter(sk_sp<SkColorFilter> outer,
176d053ce9c54d4e5937a142278359e5a4cde18095ereed                                                      sk_sp<SkColorFilter> inner) {
177db873d8677a2d4ecfe38a794a5d868301bdeeabereed    if (!outer) {
178d053ce9c54d4e5937a142278359e5a4cde18095ereed        return inner;
179db873d8677a2d4ecfe38a794a5d868301bdeeabereed    }
180db873d8677a2d4ecfe38a794a5d868301bdeeabereed    if (!inner) {
181d053ce9c54d4e5937a142278359e5a4cde18095ereed        return outer;
182db873d8677a2d4ecfe38a794a5d868301bdeeabereed    }
1838a8d841d485ff36b64d838575eb3735c1ddcf929reed
1848a8d841d485ff36b64d838575eb3735c1ddcf929reed    // Give the subclass a shot at a more optimal composition...
185d053ce9c54d4e5937a142278359e5a4cde18095ereed    auto composition = outer->makeComposed(inner);
186dc812222a7488d2a0e39b4a09c81c9f000d4b869reed    if (composition) {
187dc812222a7488d2a0e39b4a09c81c9f000d4b869reed        return composition;
188dc812222a7488d2a0e39b4a09c81c9f000d4b869reed    }
189dc812222a7488d2a0e39b4a09c81c9f000d4b869reed
190dc812222a7488d2a0e39b4a09c81c9f000d4b869reed    int count = inner->privateComposedFilterCount() + outer->privateComposedFilterCount();
191dc812222a7488d2a0e39b4a09c81c9f000d4b869reed    if (count > SK_MAX_COMPOSE_COLORFILTER_COUNT) {
19296fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
1938a8d841d485ff36b64d838575eb3735c1ddcf929reed    }
194d053ce9c54d4e5937a142278359e5a4cde18095ereed    return sk_sp<SkColorFilter>(new SkComposeColorFilter(std::move(outer), std::move(inner),count));
195db873d8677a2d4ecfe38a794a5d868301bdeeabereed}
196db873d8677a2d4ecfe38a794a5d868301bdeeabereed
197c7141eb8fba41f1e098499ef17d0bc79641d54c5reed#include "SkModeColorFilter.h"
198c7141eb8fba41f1e098499ef17d0bc79641d54c5reed
199db873d8677a2d4ecfe38a794a5d868301bdeeabereedSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkColorFilter)
200db873d8677a2d4ecfe38a794a5d868301bdeeabereedSK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkComposeColorFilter)
201c7141eb8fba41f1e098499ef17d0bc79641d54c5reedSK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkModeColorFilter)
202db873d8677a2d4ecfe38a794a5d868301bdeeabereedSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
203