1 /*
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
10 #include "SkArithmeticMode.h"
11 #include "SkBitmapSource.h"
12 #include "SkBlurImageFilter.h"
13 #include "SkColorFilter.h"
14 #include "SkColorFilterImageFilter.h"
15 #include "SkColorMatrixFilter.h"
16 #include "SkFlattenableBuffers.h"
17 #include "SkMergeImageFilter.h"
18 #include "SkMorphologyImageFilter.h"
19 #include "SkOnce.h"
20 #include "SkTestImageFilters.h"
21 #include "SkXfermodeImageFilter.h"
22
23 // More closely models how Blink's OffsetFilter works as of 10/23/13. SkOffsetImageFilter doesn't
24 // perform a draw and this one does.
25 class SimpleOffsetFilter : public SkImageFilter {
26 public:
SimpleOffsetFilter(SkScalar dx,SkScalar dy,SkImageFilter * input)27 SimpleOffsetFilter(SkScalar dx, SkScalar dy, SkImageFilter* input)
28 : SkImageFilter(input), fDX(dx), fDY(dy) {}
29
onFilterImage(Proxy * proxy,const SkBitmap & src,const SkMatrix & ctm,SkBitmap * dst,SkIPoint * offset)30 virtual bool onFilterImage(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm,
31 SkBitmap* dst, SkIPoint* offset) SK_OVERRIDE {
32 SkBitmap source = src;
33 SkImageFilter* input = getInput(0);
34 SkIPoint srcOffset = SkIPoint::Make(0, 0);
35 if (NULL != input && !input->filterImage(proxy, src, ctm, &source, &srcOffset)) {
36 return false;
37 }
38
39 SkIRect bounds;
40 source.getBounds(&bounds);
41
42 if (!this->applyCropRect(&bounds, ctm)) {
43 return false;
44 }
45
46 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
47 SkCanvas canvas(device);
48 SkPaint paint;
49 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
50 canvas.drawBitmap(source, fDX - bounds.left(), fDY - bounds.top(), &paint);
51 *dst = device->accessBitmap(false);
52 offset->fX += bounds.left();
53 offset->fY += bounds.top();
54 return true;
55 }
56
57 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SimpleOffsetFilter);
58
59 protected:
SimpleOffsetFilter(SkFlattenableReadBuffer & buffer)60 explicit SimpleOffsetFilter(SkFlattenableReadBuffer& buffer)
61 : SkImageFilter(1, buffer) {
62 fDX = buffer.readScalar();
63 fDY = buffer.readScalar();
64 }
65
flatten(SkFlattenableWriteBuffer & buffer) const66 virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
67 this->SkImageFilter::flatten(buffer);
68 buffer.writeScalar(fDX);
69 buffer.writeScalar(fDY);
70 }
71
72 private:
73 SkScalar fDX, fDY;
74 };
75
init_flattenable(int *)76 static void init_flattenable(int*) {
77 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SimpleOffsetFilter)
78 }
79
80 class ImageFiltersGraphGM : public skiagm::GM {
81 public:
ImageFiltersGraphGM()82 ImageFiltersGraphGM() : fInitialized(false) {
83 int dummy;
84 SK_DECLARE_STATIC_ONCE(once);
85 SkOnce(&once, init_flattenable, &dummy);
86 }
87
88 protected:
onShortName()89 virtual SkString onShortName() {
90 return SkString("imagefiltersgraph");
91 }
92
make_bitmap()93 void make_bitmap() {
94 fBitmap.setConfig(SkBitmap::kARGB_8888_Config, 100, 100);
95 fBitmap.allocPixels();
96 SkBitmapDevice device(fBitmap);
97 SkCanvas canvas(&device);
98 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
drawClippedBitmap(SkCanvas * canvas,const SkBitmap & bitmap,const SkPaint & paint)107 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
onISize()115 virtual SkISize onISize() { return SkISize::Make(500, 150); }
116
onDraw(SkCanvas * canvas)117 virtual void onDraw(SkCanvas* canvas) {
118 if (!fInitialized) {
119 this->make_bitmap();
120 fInitialized = true;
121 }
122 canvas->clear(0x00000000);
123 {
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));
129 SkAutoTUnref<SkImageFilter> color(SkColorFilterImageFilter::Create(cf, erode));
130 SkAutoTUnref<SkImageFilter> merge(new SkMergeImageFilter(blur, color));
131
132 SkPaint paint;
133 paint.setImageFilter(merge);
134 canvas->drawPaint(paint);
135 canvas->translate(SkIntToScalar(100), 0);
136 }
137 {
138 SkAutoTUnref<SkImageFilter> morph(new SkDilateImageFilter(5, 5));
139
140 SkScalar matrix[20] = { SK_Scalar1, 0, 0, 0, 0,
141 0, SK_Scalar1, 0, 0, 0,
142 0, 0, SK_Scalar1, 0, 0,
143 0, 0, 0, 0.5f, 0 };
144
145 SkAutoTUnref<SkColorFilter> matrixFilter(new SkColorMatrixFilter(matrix));
146 SkAutoTUnref<SkImageFilter> colorMorph(SkColorFilterImageFilter::Create(matrixFilter, morph));
147 SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(SkXfermode::kSrcOver_Mode));
148 SkAutoTUnref<SkImageFilter> blendColor(new SkXfermodeImageFilter(mode, colorMorph));
149
150 SkPaint paint;
151 paint.setImageFilter(blendColor);
152 drawClippedBitmap(canvas, fBitmap, paint);
153 canvas->translate(SkIntToScalar(100), 0);
154 }
155 {
156 SkScalar matrix[20] = { SK_Scalar1, 0, 0, 0, 0,
157 0, SK_Scalar1, 0, 0, 0,
158 0, 0, SK_Scalar1, 0, 0,
159 0, 0, 0, 0.5f, 0 };
160 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);
169 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);
184 }
185 }
186
187 private:
188 typedef GM INHERITED;
189 SkBitmap fBitmap;
190 bool fInitialized;
191 };
192
193 ///////////////////////////////////////////////////////////////////////////////
194
MyFactory(void *)195 static skiagm::GM* MyFactory(void*) { return new ImageFiltersGraphGM; }
196 static skiagm::GMRegistry reg(MyFactory);
197