144888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.org/*
244888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.org * Copyright 2012 The Android Open Source Project
344888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.org *
444888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.org * Use of this source code is governed by a BSD-style license that can be
544888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.org * found in the LICENSE file.
644888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.org */
744888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.org
844888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.org#include "SkColorFilterImageFilter.h"
944888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.org#include "SkBitmap.h"
1044888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.org#include "SkCanvas.h"
118d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org#include "SkColorMatrixFilter.h"
1244888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.org#include "SkDevice.h"
1344888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.org#include "SkColorFilter.h"
148b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h"
15c12b74dc413ef024b13e0ed478491c4b1bafe6b1cwallez#include "SkTableColorFilter.h"
168b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h"
1744888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.org
18cd9f55989e680b7f52fa21766dde0ac67ac9911fsenorblanco@chromium.orgSkColorFilterImageFilter* SkColorFilterImageFilter::Create(SkColorFilter* cf,
1924e06d5244ae96e440410e1d76e039983b2efac9senorblanco        SkImageFilter* input, const CropRect* cropRect) {
209bde31e95ddd82a4a923275bb01265740407dab1sugoi    if (NULL == cf) {
219bde31e95ddd82a4a923275bb01265740407dab1sugoi        return NULL;
229bde31e95ddd82a4a923275bb01265740407dab1sugoi    }
23c12b74dc413ef024b13e0ed478491c4b1bafe6b1cwallez
24cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    SkColorFilter* inputCF;
25cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    if (input && input->isColorFilterNode(&inputCF)) {
26cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        // This is an optimization, as it collapses the hierarchy by just combining the two
27cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        // colorfilters into a single one, which the new imagefilter will wrap.
28cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        SkAutoUnref autoUnref(inputCF);
29cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        SkAutoTUnref<SkColorFilter> newCF(SkColorFilter::CreateComposeFilter(cf, inputCF));
308a8d841d485ff36b64d838575eb3735c1ddcf929reed        if (newCF) {
3124e06d5244ae96e440410e1d76e039983b2efac9senorblanco            return SkNEW_ARGS(SkColorFilterImageFilter, (newCF, input->getInput(0), cropRect));
32c12b74dc413ef024b13e0ed478491c4b1bafe6b1cwallez        }
33cd9f55989e680b7f52fa21766dde0ac67ac9911fsenorblanco@chromium.org    }
34c12b74dc413ef024b13e0ed478491c4b1bafe6b1cwallez
3524e06d5244ae96e440410e1d76e039983b2efac9senorblanco    return SkNEW_ARGS(SkColorFilterImageFilter, (cf, input, cropRect));
36cd9f55989e680b7f52fa21766dde0ac67ac9911fsenorblanco@chromium.org}
37cd9f55989e680b7f52fa21766dde0ac67ac9911fsenorblanco@chromium.org
38194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.orgSkColorFilterImageFilter::SkColorFilterImageFilter(SkColorFilter* cf,
3924e06d5244ae96e440410e1d76e039983b2efac9senorblanco        SkImageFilter* input, const CropRect* cropRect)
4024e06d5244ae96e440410e1d76e039983b2efac9senorblanco    : INHERITED(1, &input, cropRect), fColorFilter(SkRef(cf)) {
4144888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.org}
4244888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.org
439fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkColorFilterImageFilter::CreateProc(SkReadBuffer& buffer) {
449fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
45f0f6c405fe9646be224128fc1dd24c7fc15246efreed    SkAutoTUnref<SkColorFilter> cf(buffer.readColorFilter());
4624e06d5244ae96e440410e1d76e039983b2efac9senorblanco    return Create(cf, common.getInput(0), &common.cropRect());
479fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed}
4844888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.org
498b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkColorFilterImageFilter::flatten(SkWriteBuffer& buffer) const {
5044888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.org    this->INHERITED::flatten(buffer);
5144888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.org    buffer.writeFlattenable(fColorFilter);
5244888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.org}
5344888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.org
5444888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.orgSkColorFilterImageFilter::~SkColorFilterImageFilter() {
559bde31e95ddd82a4a923275bb01265740407dab1sugoi    fColorFilter->unref();
5644888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.org}
5744888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.org
5844888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.orgbool SkColorFilterImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source,
594cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org                                             const Context& ctx,
6044888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.org                                             SkBitmap* result,
61ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                                             SkIPoint* offset) const {
6268400767be5f72e4b9750ccc8bcf0078d42869a7senorblanco@chromium.org    SkBitmap src = source;
636776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    SkIPoint srcOffset = SkIPoint::Make(0, 0);
644cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctx, &src, &srcOffset)) {
6568400767be5f72e4b9750ccc8bcf0078d42869a7senorblanco@chromium.org        return false;
6668400767be5f72e4b9750ccc8bcf0078d42869a7senorblanco@chromium.org    }
6768400767be5f72e4b9750ccc8bcf0078d42869a7senorblanco@chromium.org
68194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org    SkIRect bounds;
69118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (!this->applyCropRect(ctx, src, srcOffset, &bounds)) {
70194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org        return false;
71194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org    }
72194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org
731f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
74cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org    if (NULL == device.get()) {
75cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org        return false;
76cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org    }
7744888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.org    SkCanvas canvas(device.get());
7844888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.org    SkPaint paint;
7944888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.org
8044888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.org    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
81cd9f55989e680b7f52fa21766dde0ac67ac9911fsenorblanco@chromium.org    paint.setColorFilter(fColorFilter);
826776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    canvas.drawSprite(src, srcOffset.fX - bounds.fLeft, srcOffset.fY - bounds.fTop, &paint);
8344888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.org
8444888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.org    *result = device.get()->accessBitmap(false);
856776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    offset->fX = bounds.fLeft;
866776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    offset->fY = bounds.fTop;
8744888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.org    return true;
8844888c66d4bf03da58eb9fbd3db92eb477141aabsenorblanco@chromium.org}
898d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org
90cedc36f18b2254c5ee21f6348124886b6db4f4c2reedbool SkColorFilterImageFilter::onIsColorFilterNode(SkColorFilter** filter) const {
91cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    SkASSERT(1 == this->countInputs());
92cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    if (!this->cropRectIsSet()) {
93194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org        if (filter) {
94cedc36f18b2254c5ee21f6348124886b6db4f4c2reed            *filter = SkRef(fColorFilter);
95194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org        }
96194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org        return true;
97a1c511b8704c6c266b90860a4c68f30ca7514f9bsugoi@google.com    }
98194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org    return false;
998d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org}
100f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips
101f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips#ifndef SK_IGNORE_TO_STRING
102f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillipsvoid SkColorFilterImageFilter::toString(SkString* str) const {
103f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips    str->appendf("SkColorFilterImageFilter: (");
104f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips
10533cca886b757ed575136a628b30e845096ef94a3robertphillips    str->appendf("input: (");
10633cca886b757ed575136a628b30e845096ef94a3robertphillips
10733cca886b757ed575136a628b30e845096ef94a3robertphillips    if (this->getInput(0)) {
10833cca886b757ed575136a628b30e845096ef94a3robertphillips        this->getInput(0)->toString(str);
10933cca886b757ed575136a628b30e845096ef94a3robertphillips    }
11033cca886b757ed575136a628b30e845096ef94a3robertphillips
11133cca886b757ed575136a628b30e845096ef94a3robertphillips    str->appendf(") color filter: ");
112f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips    fColorFilter->toString(str);
113f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips
114f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips    str->append(")");
115f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips}
116f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips#endif
117