blob: 01c99efc9f9670b07dd32fbc8bb1c2c2709b6a55 [file] [log] [blame]
junov@chromium.orgf44fcdc2013-08-07 20:00:55 +00001/*
2 * Copyright 2013 Google Inc.
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 "SkDropShadowImageFilter.h"
9
junov@chromium.orgf44fcdc2013-08-07 20:00:55 +000010#include "SkBlurImageFilter.h"
11#include "SkCanvas.h"
Matt Sarett6d72ed92017-04-10 16:35:33 -040012#include "SkColorSpaceXformer.h"
Cary Clark60aaeb22017-11-03 08:06:09 -040013#include "SkImageFilterPriv.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000014#include "SkReadBuffer.h"
robertphillips0a291c72016-03-23 05:00:01 -070015#include "SkSpecialImage.h"
16#include "SkSpecialSurface.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000017#include "SkWriteBuffer.h"
junov@chromium.orgf44fcdc2013-08-07 20:00:55 +000018
robertphillips225db442016-04-17 14:27:05 -070019sk_sp<SkImageFilter> SkDropShadowImageFilter::Make(SkScalar dx, SkScalar dy,
20 SkScalar sigmaX, SkScalar sigmaY,
21 SkColor color, ShadowMode shadowMode,
22 sk_sp<SkImageFilter> input,
23 const CropRect* cropRect) {
Ben Wagner63fd7602017-10-09 15:45:33 -040024 return sk_sp<SkImageFilter>(new SkDropShadowImageFilter(dx, dy, sigmaX, sigmaY,
robertphillips225db442016-04-17 14:27:05 -070025 color, shadowMode,
26 std::move(input),
27 cropRect));
28}
29
commit-bot@chromium.orgf7efa502014-04-11 18:57:00 +000030SkDropShadowImageFilter::SkDropShadowImageFilter(SkScalar dx, SkScalar dy,
31 SkScalar sigmaX, SkScalar sigmaY, SkColor color,
robertphillipsc4169122016-04-06 08:40:59 -070032 ShadowMode shadowMode, sk_sp<SkImageFilter> input,
senorblanco24e06d52015-03-18 12:11:33 -070033 const CropRect* cropRect)
robertphillipsc4169122016-04-06 08:40:59 -070034 : INHERITED(&input, 1, cropRect)
rmistry@google.comd6bab022013-12-02 13:50:38 +000035 , fDx(dx)
36 , fDy(dy)
37 , fSigmaX(sigmaX)
38 , fSigmaY(sigmaY)
junov@chromium.orgf44fcdc2013-08-07 20:00:55 +000039 , fColor(color)
robertphillips0a291c72016-03-23 05:00:01 -070040 , fShadowMode(shadowMode) {
junov@chromium.orgf44fcdc2013-08-07 20:00:55 +000041}
42
reed60c9b582016-04-03 09:11:13 -070043sk_sp<SkFlattenable> SkDropShadowImageFilter::CreateProc(SkReadBuffer& buffer) {
reed9fa60da2014-08-21 07:59:51 -070044 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
45 SkScalar dx = buffer.readScalar();
46 SkScalar dy = buffer.readScalar();
47 SkScalar sigmaX = buffer.readScalar();
48 SkScalar sigmaY = buffer.readScalar();
49 SkColor color = buffer.readColor();
Robert Phillipsa83d0132018-01-24 14:46:38 -050050
Mike Reedde5c5022018-01-26 14:59:12 -050051 ShadowMode shadowMode = buffer.read32LE(kLast_ShadowMode);
Robert Phillipsa83d0132018-01-24 14:46:38 -050052
robertphillipsc4169122016-04-06 08:40:59 -070053 return Make(dx, dy, sigmaX, sigmaY, color, shadowMode, common.getInput(0), &common.cropRect());
reed9fa60da2014-08-21 07:59:51 -070054}
55
56void SkDropShadowImageFilter::flatten(SkWriteBuffer& buffer) const {
junov@chromium.orgf44fcdc2013-08-07 20:00:55 +000057 this->INHERITED::flatten(buffer);
58 buffer.writeScalar(fDx);
59 buffer.writeScalar(fDy);
rmistry@google.comd6bab022013-12-02 13:50:38 +000060 buffer.writeScalar(fSigmaX);
61 buffer.writeScalar(fSigmaY);
junov@chromium.orgf44fcdc2013-08-07 20:00:55 +000062 buffer.writeColor(fColor);
sugoi234f0362014-10-23 13:59:52 -070063 buffer.writeInt(static_cast<int>(fShadowMode));
junov@chromium.orgf44fcdc2013-08-07 20:00:55 +000064}
65
robertphillips2302de92016-03-24 07:26:32 -070066sk_sp<SkSpecialImage> SkDropShadowImageFilter::onFilterImage(SkSpecialImage* source,
67 const Context& ctx,
68 SkIPoint* offset) const {
robertphillips0a291c72016-03-23 05:00:01 -070069 SkIPoint inputOffset = SkIPoint::Make(0, 0);
robertphillips2302de92016-03-24 07:26:32 -070070 sk_sp<SkSpecialImage> input(this->filterInput(0, source, ctx, &inputOffset));
robertphillips0a291c72016-03-23 05:00:01 -070071 if (!input) {
72 return nullptr;
73 }
junov@chromium.orgf44fcdc2013-08-07 20:00:55 +000074
robertphillips0a291c72016-03-23 05:00:01 -070075 const SkIRect inputBounds = SkIRect::MakeXYWH(inputOffset.x(), inputOffset.y(),
76 input->width(), input->height());
rmistry@google.comd6bab022013-12-02 13:50:38 +000077 SkIRect bounds;
robertphillips0a291c72016-03-23 05:00:01 -070078 if (!this->applyCropRect(ctx, inputBounds, &bounds)) {
79 return nullptr;
rmistry@google.comd6bab022013-12-02 13:50:38 +000080 }
81
brianosmaneed6b0e2016-09-23 13:04:05 -070082 sk_sp<SkSpecialSurface> surf(source->makeSurface(ctx.outputProperties(), bounds.size()));
robertphillips0a291c72016-03-23 05:00:01 -070083 if (!surf) {
84 return nullptr;
commit-bot@chromium.orgcd3b15c2013-12-04 17:06:49 +000085 }
robertphillips0a291c72016-03-23 05:00:01 -070086
87 SkCanvas* canvas = surf->getCanvas();
88 SkASSERT(canvas);
89
90 canvas->clear(0x0);
junov@chromium.orgf44fcdc2013-08-07 20:00:55 +000091
senorblanco@chromium.orgba31f1d2014-05-07 20:56:08 +000092 SkVector sigma = SkVector::Make(fSigmaX, fSigmaY);
93 ctx.ctm().mapVectors(&sigma, 1);
senorblanco@chromium.org74bdde02014-01-28 17:57:26 +000094 sigma.fX = SkMaxScalar(0, sigma.fX);
95 sigma.fY = SkMaxScalar(0, sigma.fY);
robertphillips0a291c72016-03-23 05:00:01 -070096
junov@chromium.orgf44fcdc2013-08-07 20:00:55 +000097 SkPaint paint;
Robert Phillips92a895e2016-12-09 14:39:35 +000098 paint.setAntiAlias(true);
robertphillips6e7025a2016-04-04 04:31:25 -070099 paint.setImageFilter(SkBlurImageFilter::Make(sigma.fX, sigma.fY, nullptr));
Mike Reed7d954ad2016-10-28 15:42:34 -0400100 paint.setColorFilter(SkColorFilter::MakeModeFilter(fColor, SkBlendMode::kSrcIn));
robertphillips0a291c72016-03-23 05:00:01 -0700101
senorblanco@chromium.orgba31f1d2014-05-07 20:56:08 +0000102 SkVector offsetVec = SkVector::Make(fDx, fDy);
103 ctx.ctm().mapVectors(&offsetVec, 1);
robertphillips0a291c72016-03-23 05:00:01 -0700104
105 canvas->translate(SkIntToScalar(inputOffset.fX - bounds.fLeft),
106 SkIntToScalar(inputOffset.fY - bounds.fTop));
107 input->draw(canvas, offsetVec.fX, offsetVec.fY, &paint);
108
sugoi234f0362014-10-23 13:59:52 -0700109 if (fShadowMode == kDrawShadowAndForeground_ShadowMode) {
robertphillips0a291c72016-03-23 05:00:01 -0700110 input->draw(canvas, 0, 0, nullptr);
sugoi234f0362014-10-23 13:59:52 -0700111 }
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000112 offset->fX = bounds.fLeft;
113 offset->fY = bounds.fTop;
robertphillips2302de92016-03-24 07:26:32 -0700114 return surf->makeImageSnapshot();
junov@chromium.orgf44fcdc2013-08-07 20:00:55 +0000115}
senorblanco@chromium.org336d1d72014-01-27 21:03:17 +0000116
Matt Sarett6d72ed92017-04-10 16:35:33 -0400117sk_sp<SkImageFilter> SkDropShadowImageFilter::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
118 SkASSERT(1 == this->countInputs());
119
Florin Malita38548602017-07-06 13:39:54 -0400120 sk_sp<SkImageFilter> input = xformer->apply(this->getInput(0));
Mike Reed6d9f4292017-07-06 12:32:55 -0400121 SkColor color = xformer->apply(fColor);
122 if (input.get() != this->getInput(0) || color != fColor) {
123 return SkDropShadowImageFilter::Make(fDx, fDy, fSigmaX, fSigmaY, color,
124 fShadowMode, input, this->getCropRectIfSet());
125 }
126 return this->refMe();
Matt Sarett6d72ed92017-04-10 16:35:33 -0400127}
128
senorblancoe5e79842016-03-21 14:51:59 -0700129SkRect SkDropShadowImageFilter::computeFastBounds(const SkRect& src) const {
130 SkRect bounds = this->getInput(0) ? this->getInput(0)->computeFastBounds(src) : src;
131 SkRect shadowBounds = bounds;
senorblanco@chromium.org336d1d72014-01-27 21:03:17 +0000132 shadowBounds.offset(fDx, fDy);
Mike Reed8be952a2017-02-13 20:44:33 -0500133 shadowBounds.outset(fSigmaX * 3, fSigmaY * 3);
sugoi234f0362014-10-23 13:59:52 -0700134 if (fShadowMode == kDrawShadowAndForeground_ShadowMode) {
senorblancoe5e79842016-03-21 14:51:59 -0700135 bounds.join(shadowBounds);
sugoi234f0362014-10-23 13:59:52 -0700136 } else {
senorblancoe5e79842016-03-21 14:51:59 -0700137 bounds = shadowBounds;
sugoi234f0362014-10-23 13:59:52 -0700138 }
senorblancoe5e79842016-03-21 14:51:59 -0700139 return bounds;
senorblanco@chromium.org336d1d72014-01-27 21:03:17 +0000140}
senorblanco@chromium.orgc4b12f12014-02-05 17:51:22 +0000141
senorblancoe5e79842016-03-21 14:51:59 -0700142SkIRect SkDropShadowImageFilter::onFilterNodeBounds(const SkIRect& src, const SkMatrix& ctm,
143 MapDirection direction) const {
senorblanco@chromium.orgba31f1d2014-05-07 20:56:08 +0000144 SkVector offsetVec = SkVector::Make(fDx, fDy);
senorblancodb64af32015-12-09 10:11:43 -0800145 if (kReverse_MapDirection == direction) {
146 offsetVec.negate();
147 }
senorblanco@chromium.orgba31f1d2014-05-07 20:56:08 +0000148 ctm.mapVectors(&offsetVec, 1);
senorblancoe5e79842016-03-21 14:51:59 -0700149 SkIRect dst = src.makeOffset(SkScalarCeilToInt(offsetVec.x()),
150 SkScalarCeilToInt(offsetVec.y()));
senorblanco@chromium.orgba31f1d2014-05-07 20:56:08 +0000151 SkVector sigma = SkVector::Make(fSigmaX, fSigmaY);
152 ctm.mapVectors(&sigma, 1);
jbroman203a9932016-07-11 14:07:59 -0700153 dst.outset(
Mike Reed8be952a2017-02-13 20:44:33 -0500154 SkScalarCeilToInt(SkScalarAbs(sigma.x() * 3)),
155 SkScalarCeilToInt(SkScalarAbs(sigma.y() * 3)));
sugoi234f0362014-10-23 13:59:52 -0700156 if (fShadowMode == kDrawShadowAndForeground_ShadowMode) {
senorblancoe5e79842016-03-21 14:51:59 -0700157 dst.join(src);
sugoi234f0362014-10-23 13:59:52 -0700158 }
senorblancoe5e79842016-03-21 14:51:59 -0700159 return dst;
senorblanco@chromium.orgc4b12f12014-02-05 17:51:22 +0000160}
robertphillipsf3f5bad2014-12-19 13:49:15 -0800161
162#ifndef SK_IGNORE_TO_STRING
163void SkDropShadowImageFilter::toString(SkString* str) const {
164 str->appendf("SkDropShadowImageFilter: (");
165
166 str->appendf("dX: %f ", fDx);
167 str->appendf("dY: %f ", fDy);
168 str->appendf("sigmaX: %f ", fSigmaX);
169 str->appendf("sigmaY: %f ", fSigmaY);
170
171 str->append("Color: ");
172 str->appendHex(fColor);
173
174 static const char* gModeStrings[] = {
175 "kDrawShadowAndForeground", "kDrawShadowOnly"
176 };
177
bungeman99fe8222015-08-20 07:57:51 -0700178 static_assert(kShadowModeCount == SK_ARRAY_COUNT(gModeStrings), "enum_mismatch");
robertphillipsf3f5bad2014-12-19 13:49:15 -0800179
180 str->appendf(" mode: %s", gModeStrings[fShadowMode]);
181
182 str->append(")");
183}
184#endif