blob: 8af268e5681a9777e77fc6cf1a4f5803b07bf80c [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.org6c4e71a2013-11-20 21:32:10 +000021#include "SkTestImageFilters.h"
senorblanco@chromium.org350b4d52013-08-01 14:59:05 +000022#include "SkXfermodeImageFilter.h"
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +000023
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000024// More closely models how Blink's OffsetFilter works as of 10/23/13. SkOffsetImageFilter doesn't
25// perform a draw and this one does.
26class SimpleOffsetFilter : public SkImageFilter {
27public:
reed7daaaa42014-08-21 10:53:34 -070028 class Registrar {
29 public:
30 Registrar() {
31 SkFlattenable::Register("SimpleOffsetFilter",
32#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
33 SimpleOffsetFilter::DeepCreateProc,
34#else
35 SimpleOffsetFilter::CreateProc,
36#endif
37 SimpleOffsetFilter::GetFlattenableType());
38 }
39 };
commit-bot@chromium.org20774272014-03-18 10:28:27 +000040 static SkImageFilter* Create(SkScalar dx, SkScalar dy, SkImageFilter* input) {
41 return SkNEW_ARGS(SimpleOffsetFilter, (dx, dy, input));
42 }
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000043
senorblanco@chromium.org4cb543d2014-03-14 15:44:01 +000044 virtual bool onFilterImage(Proxy* proxy, const SkBitmap& src, const Context& ctx,
commit-bot@chromium.orgae761f72014-02-05 22:32:02 +000045 SkBitmap* dst, SkIPoint* offset) const SK_OVERRIDE {
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000046 SkBitmap source = src;
47 SkImageFilter* input = getInput(0);
48 SkIPoint srcOffset = SkIPoint::Make(0, 0);
bsalomon49f085d2014-09-05 13:34:00 -070049 if (input && !input->filterImage(proxy, src, ctx, &source, &srcOffset)) {
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000050 return false;
51 }
52
53 SkIRect bounds;
senorblanco@chromium.org11825292014-03-14 17:44:41 +000054 if (!this->applyCropRect(ctx, proxy, source, &srcOffset, &bounds, &source)) {
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000055 return false;
56 }
57
58 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
59 SkCanvas canvas(device);
60 SkPaint paint;
61 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
62 canvas.drawBitmap(source, fDX - bounds.left(), fDY - bounds.top(), &paint);
63 *dst = device->accessBitmap(false);
64 offset->fX += bounds.left();
65 offset->fY += bounds.top();
66 return true;
67 }
68
69 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SimpleOffsetFilter);
70
71protected:
reed9fa60da2014-08-21 07:59:51 -070072#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000073 explicit SimpleOffsetFilter(SkReadBuffer& buffer)
commit-bot@chromium.orgce33d602013-11-25 21:46:31 +000074 : SkImageFilter(1, buffer) {
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000075 fDX = buffer.readScalar();
76 fDY = buffer.readScalar();
77 }
reed9fa60da2014-08-21 07:59:51 -070078#endif
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000079
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000080 virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE {
reed9fa60da2014-08-21 07:59:51 -070081 this->INHERITED::flatten(buffer);
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000082 buffer.writeScalar(fDX);
83 buffer.writeScalar(fDY);
84 }
85
86private:
commit-bot@chromium.org20774272014-03-18 10:28:27 +000087 SimpleOffsetFilter(SkScalar dx, SkScalar dy, SkImageFilter* input)
reed7daaaa42014-08-21 10:53:34 -070088 : SkImageFilter(1, &input), fDX(dx), fDY(dy) {}
commit-bot@chromium.org20774272014-03-18 10:28:27 +000089
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000090 SkScalar fDX, fDY;
reed9fa60da2014-08-21 07:59:51 -070091
92 typedef SkImageFilter INHERITED;
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000093};
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +000094
reed7daaaa42014-08-21 10:53:34 -070095static SimpleOffsetFilter::Registrar gReg;
96
reed9fa60da2014-08-21 07:59:51 -070097SkFlattenable* SimpleOffsetFilter::CreateProc(SkReadBuffer& buffer) {
98 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
99 SkScalar dx = buffer.readScalar();
100 SkScalar dy = buffer.readScalar();
101 return Create(dx, dy, common.getInput(0));
102}
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +0000103
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 virtual uint32_t onGetFlags() const SK_OVERRIDE {
110 return kSkipTiled_Flag;
111 }
112
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +0000113 virtual SkString onShortName() {
114 return SkString("imagefiltersgraph");
115 }
116
117 void make_bitmap() {
reed@google.comeb9a46c2014-01-25 16:46:20 +0000118 fBitmap.allocN32Pixels(100, 100);
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000119 SkCanvas canvas(fBitmap);
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +0000120 canvas.clear(0x00000000);
121 SkPaint paint;
122 paint.setAntiAlias(true);
Cary Clark992c7b02014-07-31 08:58:44 -0400123 sk_tool_utils::set_portable_typeface(&paint);
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +0000124 paint.setColor(0xFFFFFFFF);
125 paint.setTextSize(SkIntToScalar(96));
126 const char* str = "e";
127 canvas.drawText(str, strlen(str), SkIntToScalar(20), SkIntToScalar(70), paint);
128 }
129
senorblanco@chromium.org34a849d2013-10-24 15:59:31 +0000130 void drawClippedBitmap(SkCanvas* canvas, const SkBitmap& bitmap, const SkPaint& paint) {
131 canvas->save();
132 canvas->clipRect(SkRect::MakeXYWH(0, 0,
133 SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())));
134 canvas->drawBitmap(bitmap, 0, 0, &paint);
135 canvas->restore();
136 }
137
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +0000138 virtual SkISize onISize() { return SkISize::Make(500, 150); }
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +0000139
commit-bot@chromium.org60c8d242014-05-27 16:28:43 +0000140 virtual void onOnceBeforeDraw() {
141 this->make_bitmap();
142 }
143
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +0000144 virtual void onDraw(SkCanvas* canvas) {
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +0000145 canvas->clear(0x00000000);
senorblanco@chromium.org985fa792012-10-24 15:14:26 +0000146 {
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +0000147 SkAutoTUnref<SkImageFilter> bitmapSource(SkBitmapSource::Create(fBitmap));
senorblanco@chromium.org985fa792012-10-24 15:14:26 +0000148 SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorRED,
149 SkXfermode::kSrcIn_Mode));
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +0000150 SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(4.0f, 4.0f, bitmapSource));
151 SkAutoTUnref<SkImageFilter> erode(SkErodeImageFilter::Create(4, 4, blur));
senorblanco@chromium.orgcd9f5592012-10-26 19:37:00 +0000152 SkAutoTUnref<SkImageFilter> color(SkColorFilterImageFilter::Create(cf, erode));
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +0000153 SkAutoTUnref<SkImageFilter> merge(SkMergeImageFilter::Create(blur, color));
rmistry@google.comae933ce2012-08-23 18:19:56 +0000154
senorblanco@chromium.org985fa792012-10-24 15:14:26 +0000155 SkPaint paint;
156 paint.setImageFilter(merge);
157 canvas->drawPaint(paint);
senorblanco@chromium.org34a849d2013-10-24 15:59:31 +0000158 canvas->translate(SkIntToScalar(100), 0);
senorblanco@chromium.org985fa792012-10-24 15:14:26 +0000159 }
160 {
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +0000161 SkAutoTUnref<SkImageFilter> morph(SkDilateImageFilter::Create(5, 5));
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +0000162
senorblanco@chromium.org985fa792012-10-24 15:14:26 +0000163 SkScalar matrix[20] = { SK_Scalar1, 0, 0, 0, 0,
164 0, SK_Scalar1, 0, 0, 0,
165 0, 0, SK_Scalar1, 0, 0,
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000166 0, 0, 0, 0.5f, 0 };
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +0000167
commit-bot@chromium.org727a3522014-02-21 18:46:30 +0000168 SkAutoTUnref<SkColorFilter> matrixFilter(SkColorMatrixFilter::Create(matrix));
senorblanco@chromium.orgcd9f5592012-10-26 19:37:00 +0000169 SkAutoTUnref<SkImageFilter> colorMorph(SkColorFilterImageFilter::Create(matrixFilter, morph));
senorblanco@chromium.org350b4d52013-08-01 14:59:05 +0000170 SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(SkXfermode::kSrcOver_Mode));
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +0000171 SkAutoTUnref<SkImageFilter> blendColor(SkXfermodeImageFilter::Create(mode, colorMorph));
senorblanco@chromium.org985fa792012-10-24 15:14:26 +0000172
173 SkPaint paint;
174 paint.setImageFilter(blendColor);
senorblanco@chromium.org34a849d2013-10-24 15:59:31 +0000175 drawClippedBitmap(canvas, fBitmap, paint);
176 canvas->translate(SkIntToScalar(100), 0);
senorblanco@chromium.org985fa792012-10-24 15:14:26 +0000177 }
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +0000178 {
179 SkScalar matrix[20] = { SK_Scalar1, 0, 0, 0, 0,
180 0, SK_Scalar1, 0, 0, 0,
181 0, 0, SK_Scalar1, 0, 0,
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000182 0, 0, 0, 0.5f, 0 };
commit-bot@chromium.org727a3522014-02-21 18:46:30 +0000183 SkAutoTUnref<SkColorMatrixFilter> matrixCF(SkColorMatrixFilter::Create(matrix));
184 SkAutoTUnref<SkImageFilter> matrixFilter(SkColorFilterImageFilter::Create(matrixCF));
commit-bot@chromium.org20774272014-03-18 10:28:27 +0000185 SkAutoTUnref<SkImageFilter> offsetFilter(
186 SimpleOffsetFilter::Create(10.0f, 10.f, matrixFilter));
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +0000187
188 SkAutoTUnref<SkXfermode> arith(SkArithmeticMode::Create(0, SK_Scalar1, SK_Scalar1, 0));
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +0000189 SkAutoTUnref<SkXfermodeImageFilter> arithFilter(
commit-bot@chromium.org20774272014-03-18 10:28:27 +0000190 SkXfermodeImageFilter::Create(arith, matrixFilter, offsetFilter));
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +0000191
192 SkPaint paint;
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +0000193 paint.setImageFilter(arithFilter);
senorblanco@chromium.org34a849d2013-10-24 15:59:31 +0000194 drawClippedBitmap(canvas, fBitmap, paint);
195 canvas->translate(SkIntToScalar(100), 0);
196 }
197 {
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +0000198 SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(
senorblanco@chromium.org34a849d2013-10-24 15:59:31 +0000199 SkIntToScalar(10), SkIntToScalar(10)));
200
201 SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(SkXfermode::kSrcIn_Mode));
202 SkImageFilter::CropRect cropRect(SkRect::MakeWH(SkIntToScalar(95), SkIntToScalar(100)));
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +0000203 SkAutoTUnref<SkImageFilter> blend(
204 SkXfermodeImageFilter::Create(mode, blur, NULL, &cropRect));
senorblanco@chromium.org34a849d2013-10-24 15:59:31 +0000205
206 SkPaint paint;
207 paint.setImageFilter(blend);
208 drawClippedBitmap(canvas, fBitmap, paint);
209 canvas->translate(SkIntToScalar(100), 0);
commit-bot@chromium.orgbbfe4542013-10-24 01:46:11 +0000210 }
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000211 {
212 // Test that crop offsets are absolute, not relative to the parent's crop rect.
213 SkAutoTUnref<SkColorFilter> cf1(SkColorFilter::CreateModeFilter(SK_ColorBLUE,
214 SkXfermode::kSrcIn_Mode));
215 SkAutoTUnref<SkColorFilter> cf2(SkColorFilter::CreateModeFilter(SK_ColorGREEN,
216 SkXfermode::kSrcIn_Mode));
217 SkImageFilter::CropRect outerRect(SkRect::MakeXYWH(SkIntToScalar(10), SkIntToScalar(10),
218 SkIntToScalar(80), SkIntToScalar(80)));
219 SkImageFilter::CropRect innerRect(SkRect::MakeXYWH(SkIntToScalar(20), SkIntToScalar(20),
220 SkIntToScalar(60), SkIntToScalar(60)));
221 SkAutoTUnref<SkImageFilter> color1(SkColorFilterImageFilter::Create(cf1, NULL, &outerRect));
222 SkAutoTUnref<SkImageFilter> color2(SkColorFilterImageFilter::Create(cf2, color1, &innerRect));
223
224 SkPaint paint;
225 paint.setImageFilter(color2);
226 paint.setColor(0xFFFF0000);
227 canvas->drawRect(SkRect::MakeXYWH(0, 0, 100, 100), paint);
228 canvas->translate(SkIntToScalar(100), 0);
229 }
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +0000230 }
231
232private:
233 typedef GM INHERITED;
234 SkBitmap fBitmap;
senorblanco@chromium.orgf1369ce2012-08-20 14:53:21 +0000235};
236
237///////////////////////////////////////////////////////////////////////////////
238
239static skiagm::GM* MyFactory(void*) { return new ImageFiltersGraphGM; }
240static skiagm::GMRegistry reg(MyFactory);