blob: e27a523cbc6289eec6438a562b237476aca01aa7 [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"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000018#include "SkReadBuffer.h"
19#include "SkWriteBuffer.h"
senorblanco@chromium.org4a9a6122012-12-04 14:18:50 +000020#include "SkMergeImageFilter.h"
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +000021#include "SkMorphologyImageFilter.h"
commit-bot@chromium.org6c4e71a2013-11-20 21:32:10 +000022#include "SkTestImageFilters.h"
senorblanco@chromium.org350b4d52013-08-01 14:59:05 +000023#include "SkXfermodeImageFilter.h"
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +000024
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000025// More closely models how Blink's OffsetFilter works as of 10/23/13. SkOffsetImageFilter doesn't
26// perform a draw and this one does.
27class SimpleOffsetFilter : public SkImageFilter {
28public:
reed7daaaa42014-08-21 10:53:34 -070029 class Registrar {
30 public:
31 Registrar() {
32 SkFlattenable::Register("SimpleOffsetFilter",
reed7daaaa42014-08-21 10:53:34 -070033 SimpleOffsetFilter::CreateProc,
reed7daaaa42014-08-21 10:53:34 -070034 SimpleOffsetFilter::GetFlattenableType());
35 }
36 };
commit-bot@chromium.org20774272014-03-18 10:28:27 +000037 static SkImageFilter* Create(SkScalar dx, SkScalar dy, SkImageFilter* input) {
halcanary385fe4d2015-08-26 13:07:48 -070038 return new SimpleOffsetFilter(dx, dy, input);
commit-bot@chromium.org20774272014-03-18 10:28:27 +000039 }
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000040
senorblanco@chromium.org4cb543d2014-03-14 15:44:01 +000041 virtual bool onFilterImage(Proxy* proxy, const SkBitmap& src, const Context& ctx,
mtklein36352bf2015-03-25 18:17:31 -070042 SkBitmap* dst, SkIPoint* offset) const override {
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000043 SkBitmap source = src;
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000044 SkIPoint srcOffset = SkIPoint::Make(0, 0);
senorblancob9519f82015-10-15 12:15:13 -070045 if (!this->filterInput(0, proxy, src, ctx, &source, &srcOffset)) {
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000046 return false;
47 }
48
49 SkIRect bounds;
senorblanco@chromium.org11825292014-03-14 17:44:41 +000050 if (!this->applyCropRect(ctx, proxy, source, &srcOffset, &bounds, &source)) {
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000051 return false;
52 }
53
54 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
55 SkCanvas canvas(device);
56 SkPaint paint;
57 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
58 canvas.drawBitmap(source, fDX - bounds.left(), fDY - bounds.top(), &paint);
59 *dst = device->accessBitmap(false);
60 offset->fX += bounds.left();
61 offset->fY += bounds.top();
62 return true;
63 }
64
robertphillipsf3f5bad2014-12-19 13:49:15 -080065 SK_TO_STRING_OVERRIDE()
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000066 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SimpleOffsetFilter);
67
68protected:
mtklein36352bf2015-03-25 18:17:31 -070069 void flatten(SkWriteBuffer& buffer) const override {
reed9fa60da2014-08-21 07:59:51 -070070 this->INHERITED::flatten(buffer);
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000071 buffer.writeScalar(fDX);
72 buffer.writeScalar(fDY);
73 }
74
75private:
commit-bot@chromium.org20774272014-03-18 10:28:27 +000076 SimpleOffsetFilter(SkScalar dx, SkScalar dy, SkImageFilter* input)
reed7daaaa42014-08-21 10:53:34 -070077 : SkImageFilter(1, &input), fDX(dx), fDY(dy) {}
commit-bot@chromium.org20774272014-03-18 10:28:27 +000078
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000079 SkScalar fDX, fDY;
reed9fa60da2014-08-21 07:59:51 -070080
81 typedef SkImageFilter INHERITED;
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000082};
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000083
reed7daaaa42014-08-21 10:53:34 -070084static SimpleOffsetFilter::Registrar gReg;
85
reed9fa60da2014-08-21 07:59:51 -070086SkFlattenable* SimpleOffsetFilter::CreateProc(SkReadBuffer& buffer) {
87 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
88 SkScalar dx = buffer.readScalar();
89 SkScalar dy = buffer.readScalar();
90 return Create(dx, dy, common.getInput(0));
91}
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000092
robertphillipsf3f5bad2014-12-19 13:49:15 -080093#ifndef SK_IGNORE_TO_STRING
94void SimpleOffsetFilter::toString(SkString* str) const {
95 str->appendf("SimpleOffsetFilter: (");
96 str->append(")");
97}
98#endif
99
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +0000100class ImageFiltersGraphGM : public skiagm::GM {
101public:
commit-bot@chromium.org60c8d242014-05-27 16:28:43 +0000102 ImageFiltersGraphGM() {}
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +0000103
104protected:
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +0000105
robertphillips943a4622015-09-03 13:32:33 -0700106 SkString onShortName() override {
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +0000107 return SkString("imagefiltersgraph");
108 }
109
robertphillips943a4622015-09-03 13:32:33 -0700110 SkISize onISize() override { return SkISize::Make(500, 150); }
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +0000111
robertphillips943a4622015-09-03 13:32:33 -0700112 void onOnceBeforeDraw() override {
fmalita5598b632015-09-15 11:26:13 -0700113 fImage.reset(SkImage::NewFromBitmap(
114 sk_tool_utils::create_string_bitmap(100, 100, SK_ColorWHITE, 20, 70, 96, "e")));
commit-bot@chromium.org60c8d242014-05-27 16:28:43 +0000115 }
116
robertphillips943a4622015-09-03 13:32:33 -0700117 void onDraw(SkCanvas* canvas) override {
mtklein871ad7a2015-03-27 12:33:46 -0700118 canvas->clear(SK_ColorBLACK);
senorblanco@chromium.org985fa792012-10-24 15:14:26 +0000119 {
fmalita5598b632015-09-15 11:26:13 -0700120 SkAutoTUnref<SkImageFilter> bitmapSource(SkImageSource::Create(fImage));
senorblanco@chromium.org985fa792012-10-24 15:14:26 +0000121 SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorRED,
122 SkXfermode::kSrcIn_Mode));
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +0000123 SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(4.0f, 4.0f, bitmapSource));
124 SkAutoTUnref<SkImageFilter> erode(SkErodeImageFilter::Create(4, 4, blur));
senorblanco@chromium.orgcd9f5592012-10-26 19:37:00 +0000125 SkAutoTUnref<SkImageFilter> color(SkColorFilterImageFilter::Create(cf, erode));
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +0000126 SkAutoTUnref<SkImageFilter> merge(SkMergeImageFilter::Create(blur, color));
rmistry@google.comae933ce2012-08-23 18:19:56 +0000127
senorblanco@chromium.org985fa792012-10-24 15:14:26 +0000128 SkPaint paint;
129 paint.setImageFilter(merge);
130 canvas->drawPaint(paint);
senorblanco@chromium.org34a849d2013-10-24 15:59:31 +0000131 canvas->translate(SkIntToScalar(100), 0);
senorblanco@chromium.org985fa792012-10-24 15:14:26 +0000132 }
133 {
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +0000134 SkAutoTUnref<SkImageFilter> morph(SkDilateImageFilter::Create(5, 5));
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +0000135
senorblanco@chromium.org985fa792012-10-24 15:14:26 +0000136 SkScalar matrix[20] = { SK_Scalar1, 0, 0, 0, 0,
137 0, SK_Scalar1, 0, 0, 0,
138 0, 0, SK_Scalar1, 0, 0,
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000139 0, 0, 0, 0.5f, 0 };
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +0000140
commit-bot@chromium.org727a3522014-02-21 18:46:30 +0000141 SkAutoTUnref<SkColorFilter> matrixFilter(SkColorMatrixFilter::Create(matrix));
senorblanco@chromium.orgcd9f5592012-10-26 19:37:00 +0000142 SkAutoTUnref<SkImageFilter> colorMorph(SkColorFilterImageFilter::Create(matrixFilter, morph));
senorblanco@chromium.org350b4d52013-08-01 14:59:05 +0000143 SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(SkXfermode::kSrcOver_Mode));
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +0000144 SkAutoTUnref<SkImageFilter> blendColor(SkXfermodeImageFilter::Create(mode, colorMorph));
senorblanco@chromium.org985fa792012-10-24 15:14:26 +0000145
146 SkPaint paint;
147 paint.setImageFilter(blendColor);
fmalita5598b632015-09-15 11:26:13 -0700148 DrawClippedImage(canvas, fImage, paint);
senorblanco@chromium.org34a849d2013-10-24 15:59:31 +0000149 canvas->translate(SkIntToScalar(100), 0);
senorblanco@chromium.org985fa792012-10-24 15:14:26 +0000150 }
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +0000151 {
152 SkScalar matrix[20] = { SK_Scalar1, 0, 0, 0, 0,
153 0, SK_Scalar1, 0, 0, 0,
154 0, 0, SK_Scalar1, 0, 0,
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000155 0, 0, 0, 0.5f, 0 };
commit-bot@chromium.org727a3522014-02-21 18:46:30 +0000156 SkAutoTUnref<SkColorMatrixFilter> matrixCF(SkColorMatrixFilter::Create(matrix));
157 SkAutoTUnref<SkImageFilter> matrixFilter(SkColorFilterImageFilter::Create(matrixCF));
commit-bot@chromium.org20774272014-03-18 10:28:27 +0000158 SkAutoTUnref<SkImageFilter> offsetFilter(
159 SimpleOffsetFilter::Create(10.0f, 10.f, matrixFilter));
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +0000160
161 SkAutoTUnref<SkXfermode> arith(SkArithmeticMode::Create(0, SK_Scalar1, SK_Scalar1, 0));
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +0000162 SkAutoTUnref<SkXfermodeImageFilter> arithFilter(
commit-bot@chromium.org20774272014-03-18 10:28:27 +0000163 SkXfermodeImageFilter::Create(arith, matrixFilter, offsetFilter));
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +0000164
165 SkPaint paint;
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +0000166 paint.setImageFilter(arithFilter);
fmalita5598b632015-09-15 11:26:13 -0700167 DrawClippedImage(canvas, fImage, paint);
senorblanco@chromium.org34a849d2013-10-24 15:59:31 +0000168 canvas->translate(SkIntToScalar(100), 0);
169 }
170 {
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +0000171 SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(
senorblanco@chromium.org34a849d2013-10-24 15:59:31 +0000172 SkIntToScalar(10), SkIntToScalar(10)));
173
174 SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(SkXfermode::kSrcIn_Mode));
175 SkImageFilter::CropRect cropRect(SkRect::MakeWH(SkIntToScalar(95), SkIntToScalar(100)));
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +0000176 SkAutoTUnref<SkImageFilter> blend(
halcanary96fcdcc2015-08-27 07:41:13 -0700177 SkXfermodeImageFilter::Create(mode, blur, nullptr, &cropRect));
senorblanco@chromium.org34a849d2013-10-24 15:59:31 +0000178
179 SkPaint paint;
180 paint.setImageFilter(blend);
fmalita5598b632015-09-15 11:26:13 -0700181 DrawClippedImage(canvas, fImage, paint);
senorblanco@chromium.org34a849d2013-10-24 15:59:31 +0000182 canvas->translate(SkIntToScalar(100), 0);
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +0000183 }
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000184 {
185 // Test that crop offsets are absolute, not relative to the parent's crop rect.
186 SkAutoTUnref<SkColorFilter> cf1(SkColorFilter::CreateModeFilter(SK_ColorBLUE,
187 SkXfermode::kSrcIn_Mode));
188 SkAutoTUnref<SkColorFilter> cf2(SkColorFilter::CreateModeFilter(SK_ColorGREEN,
189 SkXfermode::kSrcIn_Mode));
190 SkImageFilter::CropRect outerRect(SkRect::MakeXYWH(SkIntToScalar(10), SkIntToScalar(10),
191 SkIntToScalar(80), SkIntToScalar(80)));
192 SkImageFilter::CropRect innerRect(SkRect::MakeXYWH(SkIntToScalar(20), SkIntToScalar(20),
193 SkIntToScalar(60), SkIntToScalar(60)));
halcanary96fcdcc2015-08-27 07:41:13 -0700194 SkAutoTUnref<SkImageFilter> color1(SkColorFilterImageFilter::Create(cf1, nullptr, &outerRect));
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000195 SkAutoTUnref<SkImageFilter> color2(SkColorFilterImageFilter::Create(cf2, color1, &innerRect));
196
197 SkPaint paint;
198 paint.setImageFilter(color2);
mtklein871ad7a2015-03-27 12:33:46 -0700199 paint.setColor(SK_ColorRED);
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000200 canvas->drawRect(SkRect::MakeXYWH(0, 0, 100, 100), paint);
201 canvas->translate(SkIntToScalar(100), 0);
202 }
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +0000203 }
204
205private:
fmalita5598b632015-09-15 11:26:13 -0700206 static void DrawClippedImage(SkCanvas* canvas, const SkImage* image, const SkPaint& paint) {
207 canvas->save();
208 canvas->clipRect(SkRect::MakeIWH(image->width(), image->height()));
209 canvas->drawImage(image, 0, 0, &paint);
210 canvas->restore();
211 }
212
213 SkAutoTUnref<SkImage> fImage;
214
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +0000215 typedef GM INHERITED;
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +0000216};
217
218///////////////////////////////////////////////////////////////////////////////
219
robertphillips943a4622015-09-03 13:32:33 -0700220DEF_GM(return new ImageFiltersGraphGM;)