blob: beb3138c84e3bebea4846607883734f640daeeed [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"
robertphillips83f2e5a2016-03-24 06:31:25 -07009
senorblanco@chromium.org44888c62012-08-20 19:23:24 +000010#include "SkCanvas.h"
senorblanco@chromium.org44888c62012-08-20 19:23:24 +000011#include "SkColorFilter.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000012#include "SkReadBuffer.h"
robertphillips83f2e5a2016-03-24 06:31:25 -070013#include "SkSpecialImage.h"
14#include "SkSpecialSurface.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000015#include "SkWriteBuffer.h"
senorblanco@chromium.org44888c62012-08-20 19:23:24 +000016
reedf0280032015-10-12 11:10:10 -070017SkImageFilter* SkColorFilterImageFilter::Create(SkColorFilter* cf, SkImageFilter* input,
18 const CropRect* cropRect) {
robertphillips83f2e5a2016-03-24 06:31:25 -070019 if (!cf) {
halcanary96fcdcc2015-08-27 07:41:13 -070020 return nullptr;
sugoi9bde31e2014-10-30 14:05:14 -070021 }
cwallezc12b74d2015-01-26 07:45:53 -080022
reedcedc36f2015-03-08 04:42:52 -070023 SkColorFilter* inputCF;
24 if (input && input->isColorFilterNode(&inputCF)) {
25 // This is an optimization, as it collapses the hierarchy by just combining the two
26 // colorfilters into a single one, which the new imagefilter will wrap.
reedd053ce92016-03-22 10:17:23 -070027 sk_sp<SkColorFilter> newCF(SkColorFilter::MakeComposeFilter(sk_ref_sp(cf),
28 sk_sp<SkColorFilter>(inputCF)));
reed8a8d8412015-03-02 13:46:03 -080029 if (newCF) {
reedd053ce92016-03-22 10:17:23 -070030 return new SkColorFilterImageFilter(newCF.get(), input->getInput(0), cropRect);
cwallezc12b74d2015-01-26 07:45:53 -080031 }
senorblanco@chromium.orgcd9f5592012-10-26 19:37:00 +000032 }
cwallezc12b74d2015-01-26 07:45:53 -080033
halcanary385fe4d2015-08-26 13:07:48 -070034 return new SkColorFilterImageFilter(cf, input, cropRect);
senorblanco@chromium.orgcd9f5592012-10-26 19:37:00 +000035}
36
senorblanco@chromium.org194d7752013-07-24 22:19:24 +000037SkColorFilterImageFilter::SkColorFilterImageFilter(SkColorFilter* cf,
halcanary9d524f22016-03-29 09:03:52 -070038 SkImageFilter* input,
robertphillips83f2e5a2016-03-24 06:31:25 -070039 const CropRect* cropRect)
40 : INHERITED(1, &input, cropRect)
41 , fColorFilter(SkRef(cf)) {
senorblanco@chromium.org44888c62012-08-20 19:23:24 +000042}
43
reed9fa60da2014-08-21 07:59:51 -070044SkFlattenable* SkColorFilterImageFilter::CreateProc(SkReadBuffer& buffer) {
45 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
reedd053ce92016-03-22 10:17:23 -070046 sk_sp<SkColorFilter> cf(buffer.readColorFilter());
robertphillips2238c9d2016-03-30 13:34:16 -070047 return Create(cf.get(), common.getInput(0).get(), &common.cropRect());
reed9fa60da2014-08-21 07:59:51 -070048}
senorblanco@chromium.org44888c62012-08-20 19:23:24 +000049
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000050void SkColorFilterImageFilter::flatten(SkWriteBuffer& buffer) const {
senorblanco@chromium.org44888c62012-08-20 19:23:24 +000051 this->INHERITED::flatten(buffer);
reedd053ce92016-03-22 10:17:23 -070052 buffer.writeFlattenable(fColorFilter.get());
senorblanco@chromium.org44888c62012-08-20 19:23:24 +000053}
54
robertphillips2302de92016-03-24 07:26:32 -070055sk_sp<SkSpecialImage> SkColorFilterImageFilter::onFilterImage(SkSpecialImage* source,
56 const Context& ctx,
57 SkIPoint* offset) const {
robertphillips83f2e5a2016-03-24 06:31:25 -070058 SkIPoint inputOffset = SkIPoint::Make(0, 0);
robertphillips2302de92016-03-24 07:26:32 -070059 sk_sp<SkSpecialImage> input(this->filterInput(0, source, ctx, &inputOffset));
robertphillips83f2e5a2016-03-24 06:31:25 -070060 if (!input) {
61 return nullptr;
senorblanco@chromium.org68400762013-05-24 15:04:07 +000062 }
63
senorblanco@chromium.org194d7752013-07-24 22:19:24 +000064 SkIRect bounds;
robertphillips83f2e5a2016-03-24 06:31:25 -070065 const SkIRect inputBounds = SkIRect::MakeXYWH(inputOffset.fX, inputOffset.fY,
66 input->width(), input->height());
67 if (!this->applyCropRect(ctx, inputBounds, &bounds)) {
68 return nullptr;
senorblanco@chromium.org194d7752013-07-24 22:19:24 +000069 }
70
robertphillips83f2e5a2016-03-24 06:31:25 -070071 SkImageInfo info = SkImageInfo::MakeN32(bounds.width(), bounds.height(), kPremul_SkAlphaType);
72 sk_sp<SkSpecialSurface> surf(source->makeSurface(info));
73 if (!surf) {
74 return nullptr;
commit-bot@chromium.orgcd3b15c2013-12-04 17:06:49 +000075 }
robertphillips83f2e5a2016-03-24 06:31:25 -070076
77 SkCanvas* canvas = surf->getCanvas();
78 SkASSERT(canvas);
79
80 // TODO: it seems like this clear shouldn't be necessary (see skbug.com/5075)
81 canvas->clear(0x0);
82
senorblanco@chromium.org44888c62012-08-20 19:23:24 +000083 SkPaint paint;
84
85 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
senorblanco@chromium.orgcd9f5592012-10-26 19:37:00 +000086 paint.setColorFilter(fColorFilter);
senorblanco@chromium.org44888c62012-08-20 19:23:24 +000087
robertphillips83f2e5a2016-03-24 06:31:25 -070088 input->draw(canvas,
89 SkIntToScalar(inputOffset.fX - bounds.fLeft),
90 SkIntToScalar(inputOffset.fY - bounds.fTop),
91 &paint);
92
senorblanco@chromium.org6776b822014-01-03 21:48:22 +000093 offset->fX = bounds.fLeft;
94 offset->fY = bounds.fTop;
robertphillips2302de92016-03-24 07:26:32 -070095 return surf->makeImageSnapshot();
senorblanco@chromium.org44888c62012-08-20 19:23:24 +000096}
senorblanco@chromium.org8d21f6c2012-10-12 19:14:06 +000097
reedcedc36f2015-03-08 04:42:52 -070098bool SkColorFilterImageFilter::onIsColorFilterNode(SkColorFilter** filter) const {
99 SkASSERT(1 == this->countInputs());
100 if (!this->cropRectIsSet()) {
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000101 if (filter) {
reedd053ce92016-03-22 10:17:23 -0700102 *filter = SkRef(fColorFilter.get());
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000103 }
104 return true;
sugoi@google.coma1c511b2013-02-21 15:02:28 +0000105 }
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000106 return false;
senorblanco@chromium.org8d21f6c2012-10-12 19:14:06 +0000107}
robertphillipsf3f5bad2014-12-19 13:49:15 -0800108
senorblancoa544eda2015-12-07 07:48:34 -0800109bool SkColorFilterImageFilter::canComputeFastBounds() const {
110 if (fColorFilter->affectsTransparentBlack()) {
111 return false;
112 }
113 return INHERITED::canComputeFastBounds();
senorblanco0abdf762015-08-20 11:10:41 -0700114}
115
robertphillipsf3f5bad2014-12-19 13:49:15 -0800116#ifndef SK_IGNORE_TO_STRING
117void SkColorFilterImageFilter::toString(SkString* str) const {
118 str->appendf("SkColorFilterImageFilter: (");
119
robertphillips33cca882014-12-22 06:52:04 -0800120 str->appendf("input: (");
121
122 if (this->getInput(0)) {
123 this->getInput(0)->toString(str);
124 }
125
126 str->appendf(") color filter: ");
robertphillipsf3f5bad2014-12-19 13:49:15 -0800127 fColorFilter->toString(str);
128
129 str->append(")");
130}
131#endif