blob: dd9c37c093e57ae3e02880f52bb2878fc65929a7 [file] [log] [blame]
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +00001/*
2 * Copyright 2012 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 "gm.h"
9
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000010#include "SkArithmeticMode.h"
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +000011#include "SkDevice.h"
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +000012#include "SkBlurImageFilter.h"
senorblanco@chromium.org44888c62012-08-20 19:23:24 +000013#include "SkColorFilter.h"
14#include "SkColorFilterImageFilter.h"
commit-bot@chromium.org6c4e71a2013-11-20 21:32:10 +000015#include "SkColorMatrixFilter.h"
fmalita5598b632015-09-15 11:26:13 -070016#include "SkImage.h"
17#include "SkImageSource.h"
senorblancoeae84c22016-01-26 08:41:02 -080018#include "SkMatrixConvolutionImageFilter.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000019#include "SkReadBuffer.h"
20#include "SkWriteBuffer.h"
senorblanco@chromium.org4a9a6122012-12-04 14:18:50 +000021#include "SkMergeImageFilter.h"
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +000022#include "SkMorphologyImageFilter.h"
commit-bot@chromium.org6c4e71a2013-11-20 21:32:10 +000023#include "SkTestImageFilters.h"
senorblanco@chromium.org350b4d52013-08-01 14:59:05 +000024#include "SkXfermodeImageFilter.h"
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +000025
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000026// More closely models how Blink's OffsetFilter works as of 10/23/13. SkOffsetImageFilter doesn't
27// perform a draw and this one does.
28class SimpleOffsetFilter : public SkImageFilter {
29public:
reed7daaaa42014-08-21 10:53:34 -070030 class Registrar {
31 public:
32 Registrar() {
33 SkFlattenable::Register("SimpleOffsetFilter",
reed7daaaa42014-08-21 10:53:34 -070034 SimpleOffsetFilter::CreateProc,
reed7daaaa42014-08-21 10:53:34 -070035 SimpleOffsetFilter::GetFlattenableType());
36 }
37 };
robertphillips43c2ad42016-04-04 05:05:11 -070038 static sk_sp<SkImageFilter> Make(SkScalar dx, SkScalar dy, sk_sp<SkImageFilter> input) {
39 return sk_sp<SkImageFilter>(new SimpleOffsetFilter(dx, dy, std::move(input)));
commit-bot@chromium.org20774272014-03-18 10:28:27 +000040 }
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000041
robertphillips43c2ad42016-04-04 05:05:11 -070042 SK_TO_STRING_OVERRIDE()
43 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SimpleOffsetFilter);
44
45protected:
robertphillips48e78462016-02-17 13:57:16 -080046 bool onFilterImageDeprecated(Proxy* proxy, const SkBitmap& src, const Context& ctx,
47 SkBitmap* dst, SkIPoint* offset) const override {
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000048 SkBitmap source = src;
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000049 SkIPoint srcOffset = SkIPoint::Make(0, 0);
robertphillips48e78462016-02-17 13:57:16 -080050 if (!this->filterInputDeprecated(0, proxy, src, ctx, &source, &srcOffset)) {
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000051 return false;
52 }
53
54 SkIRect bounds;
robertphillips48e78462016-02-17 13:57:16 -080055 if (!this->applyCropRectDeprecated(ctx, proxy, source, &srcOffset, &bounds, &source)) {
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000056 return false;
57 }
58
59 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
60 SkCanvas canvas(device);
61 SkPaint paint;
62 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
63 canvas.drawBitmap(source, fDX - bounds.left(), fDY - bounds.top(), &paint);
64 *dst = device->accessBitmap(false);
65 offset->fX += bounds.left();
66 offset->fY += bounds.top();
67 return true;
68 }
69
mtklein36352bf2015-03-25 18:17:31 -070070 void flatten(SkWriteBuffer& buffer) const override {
reed9fa60da2014-08-21 07:59:51 -070071 this->INHERITED::flatten(buffer);
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000072 buffer.writeScalar(fDX);
73 buffer.writeScalar(fDY);
74 }
75
76private:
robertphillips43c2ad42016-04-04 05:05:11 -070077 SimpleOffsetFilter(SkScalar dx, SkScalar dy, sk_sp<SkImageFilter> input)
78 : SkImageFilter(&input, 1, nullptr)
79 , fDX(dx)
80 , fDY(dy) {
81 }
commit-bot@chromium.org20774272014-03-18 10:28:27 +000082
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000083 SkScalar fDX, fDY;
reed9fa60da2014-08-21 07:59:51 -070084
85 typedef SkImageFilter INHERITED;
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000086};
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000087
reed7daaaa42014-08-21 10:53:34 -070088static SimpleOffsetFilter::Registrar gReg;
89
reed60c9b582016-04-03 09:11:13 -070090sk_sp<SkFlattenable> SimpleOffsetFilter::CreateProc(SkReadBuffer& buffer) {
reed9fa60da2014-08-21 07:59:51 -070091 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
92 SkScalar dx = buffer.readScalar();
93 SkScalar dy = buffer.readScalar();
robertphillips43c2ad42016-04-04 05:05:11 -070094 return Make(dx, dy, common.getInput(0));
reed9fa60da2014-08-21 07:59:51 -070095}
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000096
robertphillipsf3f5bad2014-12-19 13:49:15 -080097#ifndef SK_IGNORE_TO_STRING
98void SimpleOffsetFilter::toString(SkString* str) const {
99 str->appendf("SimpleOffsetFilter: (");
100 str->append(")");
101}
102#endif
103
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +0000104class ImageFiltersGraphGM : public skiagm::GM {
105public:
commit-bot@chromium.org60c8d242014-05-27 16:28:43 +0000106 ImageFiltersGraphGM() {}
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +0000107
108protected:
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +0000109
robertphillips943a4622015-09-03 13:32:33 -0700110 SkString onShortName() override {
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +0000111 return SkString("imagefiltersgraph");
112 }
113
senorblancoeae84c22016-01-26 08:41:02 -0800114 SkISize onISize() override { return SkISize::Make(600, 150); }
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +0000115
robertphillips943a4622015-09-03 13:32:33 -0700116 void onOnceBeforeDraw() override {
reed9ce9d672016-03-17 10:51:11 -0700117 fImage = SkImage::MakeFromBitmap(
118 sk_tool_utils::create_string_bitmap(100, 100, SK_ColorWHITE, 20, 70, 96, "e"));
commit-bot@chromium.org60c8d242014-05-27 16:28:43 +0000119 }
120
robertphillips943a4622015-09-03 13:32:33 -0700121 void onDraw(SkCanvas* canvas) override {
mtklein871ad7a2015-03-27 12:33:46 -0700122 canvas->clear(SK_ColorBLACK);
senorblanco@chromium.org985fa792012-10-24 15:14:26 +0000123 {
robertphillips549c8992016-04-01 09:28:51 -0700124 sk_sp<SkImageFilter> bitmapSource(SkImageSource::Make(fImage));
robertphillips2238c9d2016-03-30 13:34:16 -0700125 sk_sp<SkColorFilter> cf(SkColorFilter::MakeModeFilter(SK_ColorRED,
126 SkXfermode::kSrcIn_Mode));
robertphillips6e7025a2016-04-04 04:31:25 -0700127 sk_sp<SkImageFilter> blur(SkBlurImageFilter::Make(4.0f, 4.0f, std::move(bitmapSource)));
robertphillips2238c9d2016-03-30 13:34:16 -0700128 sk_sp<SkImageFilter> erode(SkErodeImageFilter::Create(4, 4, blur.get()));
129 sk_sp<SkImageFilter> color(SkColorFilterImageFilter::Create(cf.get(), erode.get()));
130 sk_sp<SkImageFilter> merge(SkMergeImageFilter::Make(blur, color));
rmistry@google.comae933ce2012-08-23 18:19:56 +0000131
senorblanco@chromium.org985fa792012-10-24 15:14:26 +0000132 SkPaint paint;
robertphillips2238c9d2016-03-30 13:34:16 -0700133 paint.setImageFilter(std::move(merge));
senorblanco@chromium.org985fa792012-10-24 15:14:26 +0000134 canvas->drawPaint(paint);
senorblanco@chromium.org34a849d2013-10-24 15:59:31 +0000135 canvas->translate(SkIntToScalar(100), 0);
senorblanco@chromium.org985fa792012-10-24 15:14:26 +0000136 }
137 {
robertphillips43c2ad42016-04-04 05:05:11 -0700138 sk_sp<SkImageFilter> morph(SkDilateImageFilter::Create(5, 5));
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +0000139
senorblanco@chromium.org985fa792012-10-24 15:14:26 +0000140 SkScalar matrix[20] = { SK_Scalar1, 0, 0, 0, 0,
141 0, SK_Scalar1, 0, 0, 0,
142 0, 0, SK_Scalar1, 0, 0,
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000143 0, 0, 0, 0.5f, 0 };
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +0000144
robertphillips43c2ad42016-04-04 05:05:11 -0700145 sk_sp<SkColorFilter> matrixFilter(SkColorFilter::MakeMatrixFilterRowMajor255(matrix));
146 sk_sp<SkImageFilter> colorMorph(SkColorFilterImageFilter::Create(matrixFilter.get(),
147 morph.get()));
senorblanco@chromium.org985fa792012-10-24 15:14:26 +0000148 SkPaint paint;
reedcfb6bdf2016-03-29 11:32:50 -0700149 paint.setImageFilter(SkXfermodeImageFilter::Make(
robertphillips43c2ad42016-04-04 05:05:11 -0700150 SkXfermode::Make(SkXfermode::kSrcOver_Mode),
151 colorMorph.get()));
reedcfb6bdf2016-03-29 11:32:50 -0700152
reed9ce9d672016-03-17 10:51:11 -0700153 DrawClippedImage(canvas, fImage.get(), paint);
senorblanco@chromium.org34a849d2013-10-24 15:59:31 +0000154 canvas->translate(SkIntToScalar(100), 0);
senorblanco@chromium.org985fa792012-10-24 15:14:26 +0000155 }
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +0000156 {
157 SkScalar matrix[20] = { SK_Scalar1, 0, 0, 0, 0,
158 0, SK_Scalar1, 0, 0, 0,
159 0, 0, SK_Scalar1, 0, 0,
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000160 0, 0, 0, 0.5f, 0 };
robertphillips43c2ad42016-04-04 05:05:11 -0700161 sk_sp<SkColorFilter> matrixCF(SkColorFilter::MakeMatrixFilterRowMajor255(matrix));
162 sk_sp<SkImageFilter> matrixFilter(SkColorFilterImageFilter::Create(matrixCF.get()));
163 sk_sp<SkImageFilter> offsetFilter(SimpleOffsetFilter::Make(10.0f, 10.f, matrixFilter));
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +0000164
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +0000165 SkPaint paint;
reedcfb6bdf2016-03-29 11:32:50 -0700166 paint.setImageFilter(
167 SkXfermodeImageFilter::Make(SkArithmeticMode::Make(0, SK_Scalar1, SK_Scalar1, 0),
robertphillips43c2ad42016-04-04 05:05:11 -0700168 matrixFilter.get(), offsetFilter.get(), nullptr));
reedcfb6bdf2016-03-29 11:32:50 -0700169
reed9ce9d672016-03-17 10:51:11 -0700170 DrawClippedImage(canvas, fImage.get(), paint);
senorblanco@chromium.org34a849d2013-10-24 15:59:31 +0000171 canvas->translate(SkIntToScalar(100), 0);
172 }
173 {
robertphillips6e7025a2016-04-04 04:31:25 -0700174 sk_sp<SkImageFilter> blur(SkBlurImageFilter::Make(SkIntToScalar(10),
175 SkIntToScalar(10),
176 nullptr));
senorblanco@chromium.org34a849d2013-10-24 15:59:31 +0000177
senorblanco@chromium.org34a849d2013-10-24 15:59:31 +0000178 SkImageFilter::CropRect cropRect(SkRect::MakeWH(SkIntToScalar(95), SkIntToScalar(100)));
senorblanco@chromium.org34a849d2013-10-24 15:59:31 +0000179 SkPaint paint;
reedcfb6bdf2016-03-29 11:32:50 -0700180 paint.setImageFilter(
robertphillips6e7025a2016-04-04 04:31:25 -0700181 SkXfermodeImageFilter::Make(SkXfermode::Make(SkXfermode::kSrcIn_Mode), blur.get(),
reedcfb6bdf2016-03-29 11:32:50 -0700182 nullptr, &cropRect));
reed9ce9d672016-03-17 10:51:11 -0700183 DrawClippedImage(canvas, fImage.get(), paint);
senorblanco@chromium.org34a849d2013-10-24 15:59:31 +0000184 canvas->translate(SkIntToScalar(100), 0);
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +0000185 }
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000186 {
senorblancoeae84c22016-01-26 08:41:02 -0800187 // Dilate -> matrix convolution.
188 // This tests that a filter using asFragmentProcessor (matrix
189 // convolution) correctly handles a non-zero source offset
190 // (supplied by the dilate).
191 SkAutoTUnref<SkImageFilter> dilate(SkDilateImageFilter::Create(5, 5));
192
senorblancoeae84c22016-01-26 08:41:02 -0800193 SkScalar kernel[9] = {
194 SkIntToScalar(-1), SkIntToScalar( -1 ), SkIntToScalar(-1),
195 SkIntToScalar(-1), SkIntToScalar( 7 ), SkIntToScalar(-1),
196 SkIntToScalar(-1), SkIntToScalar( -1 ), SkIntToScalar(-1),
197 };
198 SkISize kernelSize = SkISize::Make(3, 3);
199 SkScalar gain = 1.0f, bias = SkIntToScalar(0);
200 SkIPoint kernelOffset = SkIPoint::Make(1, 1);
201 auto tileMode = SkMatrixConvolutionImageFilter::kClamp_TileMode;
202 bool convolveAlpha = false;
203 SkAutoTUnref<SkImageFilter> convolve(
204 SkMatrixConvolutionImageFilter::Create(kernelSize,
205 kernel,
206 gain,
207 bias,
208 kernelOffset,
209 tileMode,
210 convolveAlpha,
211 dilate));
212
213 SkPaint paint;
214 paint.setImageFilter(convolve);
reed9ce9d672016-03-17 10:51:11 -0700215 DrawClippedImage(canvas, fImage.get(), paint);
senorblancoeae84c22016-01-26 08:41:02 -0800216 canvas->translate(SkIntToScalar(100), 0);
217 }
218 {
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000219 // Test that crop offsets are absolute, not relative to the parent's crop rect.
reedd053ce92016-03-22 10:17:23 -0700220 auto cf1(SkColorFilter::MakeModeFilter(SK_ColorBLUE, SkXfermode::kSrcIn_Mode));
221 auto cf2(SkColorFilter::MakeModeFilter(SK_ColorGREEN, SkXfermode::kSrcIn_Mode));
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000222 SkImageFilter::CropRect outerRect(SkRect::MakeXYWH(SkIntToScalar(10), SkIntToScalar(10),
223 SkIntToScalar(80), SkIntToScalar(80)));
224 SkImageFilter::CropRect innerRect(SkRect::MakeXYWH(SkIntToScalar(20), SkIntToScalar(20),
225 SkIntToScalar(60), SkIntToScalar(60)));
reedd053ce92016-03-22 10:17:23 -0700226 SkAutoTUnref<SkImageFilter> color1(SkColorFilterImageFilter::Create(cf1.get(), nullptr, &outerRect));
227 SkAutoTUnref<SkImageFilter> color2(SkColorFilterImageFilter::Create(cf2.get(), color1, &innerRect));
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000228
229 SkPaint paint;
230 paint.setImageFilter(color2);
mtklein871ad7a2015-03-27 12:33:46 -0700231 paint.setColor(SK_ColorRED);
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000232 canvas->drawRect(SkRect::MakeXYWH(0, 0, 100, 100), paint);
233 canvas->translate(SkIntToScalar(100), 0);
234 }
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +0000235 }
236
237private:
fmalita5598b632015-09-15 11:26:13 -0700238 static void DrawClippedImage(SkCanvas* canvas, const SkImage* image, const SkPaint& paint) {
239 canvas->save();
240 canvas->clipRect(SkRect::MakeIWH(image->width(), image->height()));
241 canvas->drawImage(image, 0, 0, &paint);
242 canvas->restore();
243 }
244
reed9ce9d672016-03-17 10:51:11 -0700245 sk_sp<SkImage> fImage;
fmalita5598b632015-09-15 11:26:13 -0700246
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +0000247 typedef GM INHERITED;
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +0000248};
249
250///////////////////////////////////////////////////////////////////////////////
251
robertphillips943a4622015-09-03 13:32:33 -0700252DEF_GM(return new ImageFiltersGraphGM;)