blob: 2eb720e5c4cfcf093f815522af66e2839ebfb04e [file] [log] [blame]
senorblanco@chromium.org44888c62012-08-20 19:23:24 +00001/*
2 * Copyright 2012 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkColorFilterImageFilter.h"
9#include "SkBitmap.h"
10#include "SkCanvas.h"
senorblanco@chromium.org8d21f6c2012-10-12 19:14:06 +000011#include "SkColorMatrixFilter.h"
senorblanco@chromium.org44888c62012-08-20 19:23:24 +000012#include "SkDevice.h"
13#include "SkColorFilter.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000014#include "SkReadBuffer.h"
cwallezc12b74d2015-01-26 07:45:53 -080015#include "SkTableColorFilter.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000016#include "SkWriteBuffer.h"
senorblanco@chromium.org44888c62012-08-20 19:23:24 +000017
senorblanco@chromium.orgcd9f5592012-10-26 19:37:00 +000018SkColorFilterImageFilter* SkColorFilterImageFilter::Create(SkColorFilter* cf,
senorblanco24e06d52015-03-18 12:11:33 -070019 SkImageFilter* input, const CropRect* cropRect) {
sugoi9bde31e2014-10-30 14:05:14 -070020 if (NULL == cf) {
21 return NULL;
22 }
cwallezc12b74d2015-01-26 07:45:53 -080023
reedcedc36f2015-03-08 04:42:52 -070024 SkColorFilter* inputCF;
25 if (input && input->isColorFilterNode(&inputCF)) {
26 // This is an optimization, as it collapses the hierarchy by just combining the two
27 // colorfilters into a single one, which the new imagefilter will wrap.
28 SkAutoUnref autoUnref(inputCF);
29 SkAutoTUnref<SkColorFilter> newCF(SkColorFilter::CreateComposeFilter(cf, inputCF));
reed8a8d8412015-03-02 13:46:03 -080030 if (newCF) {
senorblanco24e06d52015-03-18 12:11:33 -070031 return SkNEW_ARGS(SkColorFilterImageFilter, (newCF, input->getInput(0), cropRect));
cwallezc12b74d2015-01-26 07:45:53 -080032 }
senorblanco@chromium.orgcd9f5592012-10-26 19:37:00 +000033 }
cwallezc12b74d2015-01-26 07:45:53 -080034
senorblanco24e06d52015-03-18 12:11:33 -070035 return SkNEW_ARGS(SkColorFilterImageFilter, (cf, input, cropRect));
senorblanco@chromium.orgcd9f5592012-10-26 19:37:00 +000036}
37
senorblanco@chromium.org194d7752013-07-24 22:19:24 +000038SkColorFilterImageFilter::SkColorFilterImageFilter(SkColorFilter* cf,
senorblanco24e06d52015-03-18 12:11:33 -070039 SkImageFilter* input, const CropRect* cropRect)
40 : INHERITED(1, &input, cropRect), fColorFilter(SkRef(cf)) {
senorblanco@chromium.org44888c62012-08-20 19:23:24 +000041}
42
reed9fa60da2014-08-21 07:59:51 -070043SkFlattenable* SkColorFilterImageFilter::CreateProc(SkReadBuffer& buffer) {
44 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
reedf0f6c402014-08-22 05:08:26 -070045 SkAutoTUnref<SkColorFilter> cf(buffer.readColorFilter());
senorblanco24e06d52015-03-18 12:11:33 -070046 return Create(cf, common.getInput(0), &common.cropRect());
reed9fa60da2014-08-21 07:59:51 -070047}
senorblanco@chromium.org44888c62012-08-20 19:23:24 +000048
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000049void SkColorFilterImageFilter::flatten(SkWriteBuffer& buffer) const {
senorblanco@chromium.org44888c62012-08-20 19:23:24 +000050 this->INHERITED::flatten(buffer);
senorblanco@chromium.org44888c62012-08-20 19:23:24 +000051 buffer.writeFlattenable(fColorFilter);
52}
53
54SkColorFilterImageFilter::~SkColorFilterImageFilter() {
sugoi9bde31e2014-10-30 14:05:14 -070055 fColorFilter->unref();
senorblanco@chromium.org44888c62012-08-20 19:23:24 +000056}
57
58bool SkColorFilterImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source,
senorblanco@chromium.org4cb543d2014-03-14 15:44:01 +000059 const Context& ctx,
senorblanco@chromium.org44888c62012-08-20 19:23:24 +000060 SkBitmap* result,
commit-bot@chromium.orgae761f72014-02-05 22:32:02 +000061 SkIPoint* offset) const {
senorblanco@chromium.org68400762013-05-24 15:04:07 +000062 SkBitmap src = source;
senorblanco@chromium.org6776b822014-01-03 21:48:22 +000063 SkIPoint srcOffset = SkIPoint::Make(0, 0);
senorblanco@chromium.org4cb543d2014-03-14 15:44:01 +000064 if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctx, &src, &srcOffset)) {
senorblanco@chromium.org68400762013-05-24 15:04:07 +000065 return false;
66 }
67
senorblanco@chromium.org194d7752013-07-24 22:19:24 +000068 SkIRect bounds;
senorblanco@chromium.org11825292014-03-14 17:44:41 +000069 if (!this->applyCropRect(ctx, src, srcOffset, &bounds)) {
senorblanco@chromium.org194d7752013-07-24 22:19:24 +000070 return false;
71 }
72
robertphillips@google.com1f2f3382013-08-29 11:54:56 +000073 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
commit-bot@chromium.orgcd3b15c2013-12-04 17:06:49 +000074 if (NULL == device.get()) {
75 return false;
76 }
senorblanco@chromium.org44888c62012-08-20 19:23:24 +000077 SkCanvas canvas(device.get());
78 SkPaint paint;
79
80 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
senorblanco@chromium.orgcd9f5592012-10-26 19:37:00 +000081 paint.setColorFilter(fColorFilter);
senorblanco@chromium.org6776b822014-01-03 21:48:22 +000082 canvas.drawSprite(src, srcOffset.fX - bounds.fLeft, srcOffset.fY - bounds.fTop, &paint);
senorblanco@chromium.org44888c62012-08-20 19:23:24 +000083
84 *result = device.get()->accessBitmap(false);
senorblanco@chromium.org6776b822014-01-03 21:48:22 +000085 offset->fX = bounds.fLeft;
86 offset->fY = bounds.fTop;
senorblanco@chromium.org44888c62012-08-20 19:23:24 +000087 return true;
88}
senorblanco@chromium.org8d21f6c2012-10-12 19:14:06 +000089
reedcedc36f2015-03-08 04:42:52 -070090bool SkColorFilterImageFilter::onIsColorFilterNode(SkColorFilter** filter) const {
91 SkASSERT(1 == this->countInputs());
92 if (!this->cropRectIsSet()) {
senorblanco@chromium.org194d7752013-07-24 22:19:24 +000093 if (filter) {
reedcedc36f2015-03-08 04:42:52 -070094 *filter = SkRef(fColorFilter);
senorblanco@chromium.org194d7752013-07-24 22:19:24 +000095 }
96 return true;
sugoi@google.coma1c511b2013-02-21 15:02:28 +000097 }
senorblanco@chromium.org194d7752013-07-24 22:19:24 +000098 return false;
senorblanco@chromium.org8d21f6c2012-10-12 19:14:06 +000099}
robertphillipsf3f5bad2014-12-19 13:49:15 -0800100
101#ifndef SK_IGNORE_TO_STRING
102void SkColorFilterImageFilter::toString(SkString* str) const {
103 str->appendf("SkColorFilterImageFilter: (");
104
robertphillips33cca882014-12-22 06:52:04 -0800105 str->appendf("input: (");
106
107 if (this->getInput(0)) {
108 this->getInput(0)->toString(str);
109 }
110
111 str->appendf(") color filter: ");
robertphillipsf3f5bad2014-12-19 13:49:15 -0800112 fColorFilter->toString(str);
113
114 str->append(")");
115}
116#endif