blob: 92e7e2c096b1bd1525f87930f21b1b8833c6d294 [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"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000012#include "SkReadBuffer.h"
robertphillips0a291c72016-03-23 05:00:01 -070013#include "SkSpecialImage.h"
14#include "SkSpecialSurface.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000015#include "SkWriteBuffer.h"
junov@chromium.orgf44fcdc2013-08-07 20:00:55 +000016
commit-bot@chromium.orgf7efa502014-04-11 18:57:00 +000017SkDropShadowImageFilter::SkDropShadowImageFilter(SkScalar dx, SkScalar dy,
18 SkScalar sigmaX, SkScalar sigmaY, SkColor color,
robertphillipsc4169122016-04-06 08:40:59 -070019 ShadowMode shadowMode, sk_sp<SkImageFilter> input,
senorblanco24e06d52015-03-18 12:11:33 -070020 const CropRect* cropRect)
robertphillipsc4169122016-04-06 08:40:59 -070021 : INHERITED(&input, 1, cropRect)
rmistry@google.comd6bab022013-12-02 13:50:38 +000022 , fDx(dx)
23 , fDy(dy)
24 , fSigmaX(sigmaX)
25 , fSigmaY(sigmaY)
junov@chromium.orgf44fcdc2013-08-07 20:00:55 +000026 , fColor(color)
robertphillips0a291c72016-03-23 05:00:01 -070027 , fShadowMode(shadowMode) {
junov@chromium.orgf44fcdc2013-08-07 20:00:55 +000028}
29
reed60c9b582016-04-03 09:11:13 -070030sk_sp<SkFlattenable> SkDropShadowImageFilter::CreateProc(SkReadBuffer& buffer) {
reed9fa60da2014-08-21 07:59:51 -070031 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
32 SkScalar dx = buffer.readScalar();
33 SkScalar dy = buffer.readScalar();
34 SkScalar sigmaX = buffer.readScalar();
35 SkScalar sigmaY = buffer.readScalar();
36 SkColor color = buffer.readColor();
sugoi234f0362014-10-23 13:59:52 -070037 ShadowMode shadowMode = buffer.isVersionLT(SkReadBuffer::kDropShadowMode_Version) ?
38 kDrawShadowAndForeground_ShadowMode :
39 static_cast<ShadowMode>(buffer.readInt());
robertphillipsc4169122016-04-06 08:40:59 -070040 return Make(dx, dy, sigmaX, sigmaY, color, shadowMode, common.getInput(0), &common.cropRect());
reed9fa60da2014-08-21 07:59:51 -070041}
42
43void SkDropShadowImageFilter::flatten(SkWriteBuffer& buffer) const {
junov@chromium.orgf44fcdc2013-08-07 20:00:55 +000044 this->INHERITED::flatten(buffer);
45 buffer.writeScalar(fDx);
46 buffer.writeScalar(fDy);
rmistry@google.comd6bab022013-12-02 13:50:38 +000047 buffer.writeScalar(fSigmaX);
48 buffer.writeScalar(fSigmaY);
junov@chromium.orgf44fcdc2013-08-07 20:00:55 +000049 buffer.writeColor(fColor);
sugoi234f0362014-10-23 13:59:52 -070050 buffer.writeInt(static_cast<int>(fShadowMode));
junov@chromium.orgf44fcdc2013-08-07 20:00:55 +000051}
52
robertphillips2302de92016-03-24 07:26:32 -070053sk_sp<SkSpecialImage> SkDropShadowImageFilter::onFilterImage(SkSpecialImage* source,
54 const Context& ctx,
55 SkIPoint* offset) const {
robertphillips0a291c72016-03-23 05:00:01 -070056 SkIPoint inputOffset = SkIPoint::Make(0, 0);
robertphillips2302de92016-03-24 07:26:32 -070057 sk_sp<SkSpecialImage> input(this->filterInput(0, source, ctx, &inputOffset));
robertphillips0a291c72016-03-23 05:00:01 -070058 if (!input) {
59 return nullptr;
60 }
junov@chromium.orgf44fcdc2013-08-07 20:00:55 +000061
robertphillips0a291c72016-03-23 05:00:01 -070062 const SkIRect inputBounds = SkIRect::MakeXYWH(inputOffset.x(), inputOffset.y(),
63 input->width(), input->height());
rmistry@google.comd6bab022013-12-02 13:50:38 +000064 SkIRect bounds;
robertphillips0a291c72016-03-23 05:00:01 -070065 if (!this->applyCropRect(ctx, inputBounds, &bounds)) {
66 return nullptr;
rmistry@google.comd6bab022013-12-02 13:50:38 +000067 }
68
robertphillips0a291c72016-03-23 05:00:01 -070069 const SkImageInfo info = SkImageInfo::MakeN32(bounds.width(), bounds.height(),
70 kPremul_SkAlphaType);
71 sk_sp<SkSpecialSurface> surf(source->makeSurface(info));
72 if (!surf) {
73 return nullptr;
commit-bot@chromium.orgcd3b15c2013-12-04 17:06:49 +000074 }
robertphillips0a291c72016-03-23 05:00:01 -070075
76 SkCanvas* canvas = surf->getCanvas();
77 SkASSERT(canvas);
78
79 canvas->clear(0x0);
junov@chromium.orgf44fcdc2013-08-07 20:00:55 +000080
senorblanco@chromium.orgba31f1d2014-05-07 20:56:08 +000081 SkVector sigma = SkVector::Make(fSigmaX, fSigmaY);
82 ctx.ctm().mapVectors(&sigma, 1);
senorblanco@chromium.org74bdde02014-01-28 17:57:26 +000083 sigma.fX = SkMaxScalar(0, sigma.fX);
84 sigma.fY = SkMaxScalar(0, sigma.fY);
robertphillips0a291c72016-03-23 05:00:01 -070085
junov@chromium.orgf44fcdc2013-08-07 20:00:55 +000086 SkPaint paint;
robertphillips6e7025a2016-04-04 04:31:25 -070087 paint.setImageFilter(SkBlurImageFilter::Make(sigma.fX, sigma.fY, nullptr));
reedd053ce92016-03-22 10:17:23 -070088 paint.setColorFilter(SkColorFilter::MakeModeFilter(fColor, SkXfermode::kSrcIn_Mode));
junov@chromium.orgf44fcdc2013-08-07 20:00:55 +000089 paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
robertphillips0a291c72016-03-23 05:00:01 -070090
senorblanco@chromium.orgba31f1d2014-05-07 20:56:08 +000091 SkVector offsetVec = SkVector::Make(fDx, fDy);
92 ctx.ctm().mapVectors(&offsetVec, 1);
robertphillips0a291c72016-03-23 05:00:01 -070093
94 canvas->translate(SkIntToScalar(inputOffset.fX - bounds.fLeft),
95 SkIntToScalar(inputOffset.fY - bounds.fTop));
96 input->draw(canvas, offsetVec.fX, offsetVec.fY, &paint);
97
sugoi234f0362014-10-23 13:59:52 -070098 if (fShadowMode == kDrawShadowAndForeground_ShadowMode) {
robertphillips0a291c72016-03-23 05:00:01 -070099 input->draw(canvas, 0, 0, nullptr);
sugoi234f0362014-10-23 13:59:52 -0700100 }
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000101 offset->fX = bounds.fLeft;
102 offset->fY = bounds.fTop;
robertphillips2302de92016-03-24 07:26:32 -0700103 return surf->makeImageSnapshot();
junov@chromium.orgf44fcdc2013-08-07 20:00:55 +0000104}
senorblanco@chromium.org336d1d72014-01-27 21:03:17 +0000105
senorblancoe5e79842016-03-21 14:51:59 -0700106SkRect SkDropShadowImageFilter::computeFastBounds(const SkRect& src) const {
107 SkRect bounds = this->getInput(0) ? this->getInput(0)->computeFastBounds(src) : src;
108 SkRect shadowBounds = bounds;
senorblanco@chromium.org336d1d72014-01-27 21:03:17 +0000109 shadowBounds.offset(fDx, fDy);
110 shadowBounds.outset(SkScalarMul(fSigmaX, SkIntToScalar(3)),
111 SkScalarMul(fSigmaY, SkIntToScalar(3)));
sugoi234f0362014-10-23 13:59:52 -0700112 if (fShadowMode == kDrawShadowAndForeground_ShadowMode) {
senorblancoe5e79842016-03-21 14:51:59 -0700113 bounds.join(shadowBounds);
sugoi234f0362014-10-23 13:59:52 -0700114 } else {
senorblancoe5e79842016-03-21 14:51:59 -0700115 bounds = shadowBounds;
sugoi234f0362014-10-23 13:59:52 -0700116 }
senorblancoe5e79842016-03-21 14:51:59 -0700117 return bounds;
senorblanco@chromium.org336d1d72014-01-27 21:03:17 +0000118}
senorblanco@chromium.orgc4b12f12014-02-05 17:51:22 +0000119
senorblancoe5e79842016-03-21 14:51:59 -0700120SkIRect SkDropShadowImageFilter::onFilterNodeBounds(const SkIRect& src, const SkMatrix& ctm,
121 MapDirection direction) const {
senorblanco@chromium.orgba31f1d2014-05-07 20:56:08 +0000122 SkVector offsetVec = SkVector::Make(fDx, fDy);
senorblancodb64af32015-12-09 10:11:43 -0800123 if (kReverse_MapDirection == direction) {
124 offsetVec.negate();
125 }
senorblanco@chromium.orgba31f1d2014-05-07 20:56:08 +0000126 ctm.mapVectors(&offsetVec, 1);
senorblancoe5e79842016-03-21 14:51:59 -0700127 SkIRect dst = src.makeOffset(SkScalarCeilToInt(offsetVec.x()),
128 SkScalarCeilToInt(offsetVec.y()));
senorblanco@chromium.orgba31f1d2014-05-07 20:56:08 +0000129 SkVector sigma = SkVector::Make(fSigmaX, fSigmaY);
130 ctm.mapVectors(&sigma, 1);
senorblancoe5e79842016-03-21 14:51:59 -0700131 dst.outset(SkScalarCeilToInt(SkScalarMul(sigma.x(), SkIntToScalar(3))),
senorblancodb64af32015-12-09 10:11:43 -0800132 SkScalarCeilToInt(SkScalarMul(sigma.y(), SkIntToScalar(3))));
sugoi234f0362014-10-23 13:59:52 -0700133 if (fShadowMode == kDrawShadowAndForeground_ShadowMode) {
senorblancoe5e79842016-03-21 14:51:59 -0700134 dst.join(src);
sugoi234f0362014-10-23 13:59:52 -0700135 }
senorblancoe5e79842016-03-21 14:51:59 -0700136 return dst;
senorblanco@chromium.orgc4b12f12014-02-05 17:51:22 +0000137}
robertphillipsf3f5bad2014-12-19 13:49:15 -0800138
139#ifndef SK_IGNORE_TO_STRING
140void SkDropShadowImageFilter::toString(SkString* str) const {
141 str->appendf("SkDropShadowImageFilter: (");
142
143 str->appendf("dX: %f ", fDx);
144 str->appendf("dY: %f ", fDy);
145 str->appendf("sigmaX: %f ", fSigmaX);
146 str->appendf("sigmaY: %f ", fSigmaY);
147
148 str->append("Color: ");
149 str->appendHex(fColor);
150
151 static const char* gModeStrings[] = {
152 "kDrawShadowAndForeground", "kDrawShadowOnly"
153 };
154
bungeman99fe8222015-08-20 07:57:51 -0700155 static_assert(kShadowModeCount == SK_ARRAY_COUNT(gModeStrings), "enum_mismatch");
robertphillipsf3f5bad2014-12-19 13:49:15 -0800156
157 str->appendf(" mode: %s", gModeStrings[fShadowMode]);
158
159 str->append(")");
160}
161#endif