blob: 882918cb7b7d3c4c1117b4c76dc2358e5f4d3787 [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 "SkBitmapSource.h"
13#include "SkBlurImageFilter.h"
senorblanco@chromium.org44888c62012-08-20 19:23:24 +000014#include "SkColorFilter.h"
15#include "SkColorFilterImageFilter.h"
commit-bot@chromium.org6c4e71a2013-11-20 21:32:10 +000016#include "SkColorMatrixFilter.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000017#include "SkReadBuffer.h"
18#include "SkWriteBuffer.h"
senorblanco@chromium.org4a9a6122012-12-04 14:18:50 +000019#include "SkMergeImageFilter.h"
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +000020#include "SkMorphologyImageFilter.h"
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000021#include "SkOnce.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:
29 SimpleOffsetFilter(SkScalar dx, SkScalar dy, SkImageFilter* input)
30 : SkImageFilter(input), fDX(dx), fDY(dy) {}
31
32 virtual bool onFilterImage(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm,
commit-bot@chromium.orgae761f72014-02-05 22:32:02 +000033 SkBitmap* dst, SkIPoint* offset) const SK_OVERRIDE {
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000034 SkBitmap source = src;
35 SkImageFilter* input = getInput(0);
36 SkIPoint srcOffset = SkIPoint::Make(0, 0);
37 if (NULL != input && !input->filterImage(proxy, src, ctm, &source, &srcOffset)) {
38 return false;
39 }
40
41 SkIRect bounds;
42 source.getBounds(&bounds);
43
44 if (!this->applyCropRect(&bounds, ctm)) {
45 return false;
46 }
47
48 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
49 SkCanvas canvas(device);
50 SkPaint paint;
51 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
52 canvas.drawBitmap(source, fDX - bounds.left(), fDY - bounds.top(), &paint);
53 *dst = device->accessBitmap(false);
54 offset->fX += bounds.left();
55 offset->fY += bounds.top();
56 return true;
57 }
58
59 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SimpleOffsetFilter);
60
61protected:
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000062 explicit SimpleOffsetFilter(SkReadBuffer& buffer)
commit-bot@chromium.orgce33d602013-11-25 21:46:31 +000063 : SkImageFilter(1, buffer) {
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000064 fDX = buffer.readScalar();
65 fDY = buffer.readScalar();
66 }
67
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000068 virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE {
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000069 this->SkImageFilter::flatten(buffer);
70 buffer.writeScalar(fDX);
71 buffer.writeScalar(fDY);
72 }
73
74private:
75 SkScalar fDX, fDY;
76};
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000077
78static void init_flattenable(int*) {
79 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SimpleOffsetFilter)
80}
81
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +000082class ImageFiltersGraphGM : public skiagm::GM {
83public:
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000084 ImageFiltersGraphGM() : fInitialized(false) {
85 int dummy;
86 SK_DECLARE_STATIC_ONCE(once);
87 SkOnce(&once, init_flattenable, &dummy);
88 }
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +000089
90protected:
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +000091 virtual SkString onShortName() {
92 return SkString("imagefiltersgraph");
93 }
94
95 void make_bitmap() {
reed@google.comeb9a46c2014-01-25 16:46:20 +000096 fBitmap.allocN32Pixels(100, 100);
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +000097 SkCanvas canvas(fBitmap);
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +000098 canvas.clear(0x00000000);
99 SkPaint paint;
100 paint.setAntiAlias(true);
101 paint.setColor(0xFFFFFFFF);
102 paint.setTextSize(SkIntToScalar(96));
103 const char* str = "e";
104 canvas.drawText(str, strlen(str), SkIntToScalar(20), SkIntToScalar(70), paint);
105 }
106
senorblanco@chromium.org34a849d2013-10-24 15:59:31 +0000107 void drawClippedBitmap(SkCanvas* canvas, const SkBitmap& bitmap, const SkPaint& paint) {
108 canvas->save();
109 canvas->clipRect(SkRect::MakeXYWH(0, 0,
110 SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())));
111 canvas->drawBitmap(bitmap, 0, 0, &paint);
112 canvas->restore();
113 }
114
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +0000115 virtual SkISize onISize() { return SkISize::Make(500, 150); }
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +0000116
117 virtual void onDraw(SkCanvas* canvas) {
118 if (!fInitialized) {
119 this->make_bitmap();
120 fInitialized = true;
121 }
122 canvas->clear(0x00000000);
senorblanco@chromium.org985fa792012-10-24 15:14:26 +0000123 {
124 SkAutoTUnref<SkImageFilter> bitmapSource(new SkBitmapSource(fBitmap));
125 SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorRED,
126 SkXfermode::kSrcIn_Mode));
127 SkAutoTUnref<SkImageFilter> blur(new SkBlurImageFilter(4.0f, 4.0f, bitmapSource));
128 SkAutoTUnref<SkImageFilter> erode(new SkErodeImageFilter(4, 4, blur));
senorblanco@chromium.orgcd9f5592012-10-26 19:37:00 +0000129 SkAutoTUnref<SkImageFilter> color(SkColorFilterImageFilter::Create(cf, erode));
senorblanco@chromium.org985fa792012-10-24 15:14:26 +0000130 SkAutoTUnref<SkImageFilter> merge(new SkMergeImageFilter(blur, color));
rmistry@google.comae933ce2012-08-23 18:19:56 +0000131
senorblanco@chromium.org985fa792012-10-24 15:14:26 +0000132 SkPaint paint;
133 paint.setImageFilter(merge);
134 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 {
138 SkAutoTUnref<SkImageFilter> morph(new SkDilateImageFilter(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
senorblanco@chromium.org985fa792012-10-24 15:14:26 +0000145 SkAutoTUnref<SkColorFilter> matrixFilter(new SkColorMatrixFilter(matrix));
senorblanco@chromium.orgcd9f5592012-10-26 19:37:00 +0000146 SkAutoTUnref<SkImageFilter> colorMorph(SkColorFilterImageFilter::Create(matrixFilter, morph));
senorblanco@chromium.org350b4d52013-08-01 14:59:05 +0000147 SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(SkXfermode::kSrcOver_Mode));
148 SkAutoTUnref<SkImageFilter> blendColor(new SkXfermodeImageFilter(mode, colorMorph));
senorblanco@chromium.org985fa792012-10-24 15:14:26 +0000149
150 SkPaint paint;
151 paint.setImageFilter(blendColor);
senorblanco@chromium.org34a849d2013-10-24 15:59:31 +0000152 drawClippedBitmap(canvas, fBitmap, paint);
153 canvas->translate(SkIntToScalar(100), 0);
senorblanco@chromium.org985fa792012-10-24 15:14:26 +0000154 }
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +0000155 {
156 SkScalar matrix[20] = { SK_Scalar1, 0, 0, 0, 0,
157 0, SK_Scalar1, 0, 0, 0,
158 0, 0, SK_Scalar1, 0, 0,
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000159 0, 0, 0, 0.5f, 0 };
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +0000160 SkColorMatrixFilter matrixCF(matrix);
161 SkAutoTUnref<SkImageFilter> matrixFilter(SkColorFilterImageFilter::Create(&matrixCF));
162 SimpleOffsetFilter offsetFilter(SkIntToScalar(10), SkIntToScalar(10), matrixFilter);
163
164 SkAutoTUnref<SkXfermode> arith(SkArithmeticMode::Create(0, SK_Scalar1, SK_Scalar1, 0));
165 SkXfermodeImageFilter arithFilter(arith, matrixFilter, &offsetFilter);
166
167 SkPaint paint;
168 paint.setImageFilter(&arithFilter);
senorblanco@chromium.org34a849d2013-10-24 15:59:31 +0000169 drawClippedBitmap(canvas, fBitmap, paint);
170 canvas->translate(SkIntToScalar(100), 0);
171 }
172 {
173 SkAutoTUnref<SkImageFilter> blur(new SkBlurImageFilter(
174 SkIntToScalar(10), SkIntToScalar(10)));
175
176 SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(SkXfermode::kSrcIn_Mode));
177 SkImageFilter::CropRect cropRect(SkRect::MakeWH(SkIntToScalar(95), SkIntToScalar(100)));
178 SkAutoTUnref<SkImageFilter> blend(new SkXfermodeImageFilter(mode, blur, NULL, &cropRect));
179
180 SkPaint paint;
181 paint.setImageFilter(blend);
182 drawClippedBitmap(canvas, fBitmap, paint);
183 canvas->translate(SkIntToScalar(100), 0);
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +0000184 }
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000185 {
186 // Test that crop offsets are absolute, not relative to the parent's crop rect.
187 SkAutoTUnref<SkColorFilter> cf1(SkColorFilter::CreateModeFilter(SK_ColorBLUE,
188 SkXfermode::kSrcIn_Mode));
189 SkAutoTUnref<SkColorFilter> cf2(SkColorFilter::CreateModeFilter(SK_ColorGREEN,
190 SkXfermode::kSrcIn_Mode));
191 SkImageFilter::CropRect outerRect(SkRect::MakeXYWH(SkIntToScalar(10), SkIntToScalar(10),
192 SkIntToScalar(80), SkIntToScalar(80)));
193 SkImageFilter::CropRect innerRect(SkRect::MakeXYWH(SkIntToScalar(20), SkIntToScalar(20),
194 SkIntToScalar(60), SkIntToScalar(60)));
195 SkAutoTUnref<SkImageFilter> color1(SkColorFilterImageFilter::Create(cf1, NULL, &outerRect));
196 SkAutoTUnref<SkImageFilter> color2(SkColorFilterImageFilter::Create(cf2, color1, &innerRect));
197
198 SkPaint paint;
199 paint.setImageFilter(color2);
200 paint.setColor(0xFFFF0000);
201 canvas->drawRect(SkRect::MakeXYWH(0, 0, 100, 100), paint);
202 canvas->translate(SkIntToScalar(100), 0);
203 }
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +0000204 }
205
206private:
207 typedef GM INHERITED;
208 SkBitmap fBitmap;
209 bool fInitialized;
210};
211
212///////////////////////////////////////////////////////////////////////////////
213
214static skiagm::GM* MyFactory(void*) { return new ImageFiltersGraphGM; }
215static skiagm::GMRegistry reg(MyFactory);