blob: d15c6ebc905dc3030a3af839a128672ae3a3d6e6 [file] [log] [blame]
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +00001/*
2 * Copyright 2013 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#include "SampleCode.h"
8#include "SkBicubicImageFilter.h"
commit-bot@chromium.org77e079a2013-10-28 15:52:02 +00009#include "SkBitmapDevice.h"
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +000010#include "SkBitmapSource.h"
11#include "SkBlurImageFilter.h"
12#include "SkCanvas.h"
13#include "SkColorFilter.h"
14#include "SkColorFilterImageFilter.h"
15#include "SkComposeImageFilter.h"
commit-bot@chromium.org77e079a2013-10-28 15:52:02 +000016#include "SkData.h"
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +000017#include "SkDisplacementMapEffect.h"
18#include "SkDropShadowImageFilter.h"
19#include "SkFlattenableSerialization.h"
20#include "SkLightingImageFilter.h"
21#include "SkMagnifierImageFilter.h"
22#include "SkMergeImageFilter.h"
23#include "SkMorphologyImageFilter.h"
24#include "SkOffsetImageFilter.h"
25#include "SkPerlinNoiseShader.h"
26#include "SkRandom.h"
27#include "SkRectShaderImageFilter.h"
commit-bot@chromium.orgcd3b15c2013-12-04 17:06:49 +000028#include "SkTileImageFilter.h"
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +000029#include "SkView.h"
30#include "SkXfermodeImageFilter.h"
commit-bot@chromium.orgcd3b15c2013-12-04 17:06:49 +000031#include <stdio.h>
32#include <time.h>
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +000033
commit-bot@chromium.orgcd3b15c2013-12-04 17:06:49 +000034static const uint32_t kSeed = (uint32_t)(time(NULL));
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +000035static SkRandom gRand(kSeed);
36static bool return_large = false;
37static bool return_undef = false;
38
39static const int kBitmapSize = 24;
40
41static int R(float x) {
42 return (int)floor(SkScalarToFloat(gRand.nextUScalar1()) * x);
43}
44
45#if defined _WIN32
46#pragma warning ( push )
47// we are intentionally causing an overflow here
48// (warning C4756: overflow in constant arithmetic)
49#pragma warning ( disable : 4756 )
50#endif
51
52static float huge() {
53 double d = 1e100;
54 float f = (float)d;
55 return f;
56}
57
58#if defined _WIN32
59#pragma warning ( pop )
60#endif
61
62static float make_number(bool positiveOnly) {
63 float f = positiveOnly ? 1.0f : 0.0f;
64 float v = f;
65 int sel;
66
67 if (return_large) sel = R(6); else sel = R(4);
68 if (!return_undef && sel == 0) sel = 1;
69
70 if (R(2) == 1) v = (float)(R(100)+f); else
71
72 switch (sel) {
73 case 0: break;
74 case 1: v = f; break;
75 case 2: v = 0.000001f; break;
76 case 3: v = 10000.0f; break;
77 case 4: v = 2000000000.0f; break;
78 case 5: v = huge(); break;
79 }
80
81 if (!positiveOnly && (R(4) == 1)) v = -v;
82 return v;
83}
84
85static SkScalar make_scalar(bool positiveOnly = false) {
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +000086 return make_number(positiveOnly);
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +000087}
88
commit-bot@chromium.orgcd3b15c2013-12-04 17:06:49 +000089static SkRect make_rect() {
90 return SkRect::MakeWH(SkIntToScalar(R(static_cast<float>(kBitmapSize))),
91 SkIntToScalar(R(static_cast<float>(kBitmapSize))));
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +000092}
93
94static SkXfermode::Mode make_xfermode() {
95 return static_cast<SkXfermode::Mode>(R(SkXfermode::kLastMode+1));
96}
97
98static SkColor make_color() {
99 return (R(2) == 1) ? 0xFFC0F0A0 : 0xFF000090;
100}
101
102static SkPoint3 make_point() {
103 return SkPoint3(make_scalar(), make_scalar(), make_scalar(true));
104}
105
106static SkDisplacementMapEffect::ChannelSelectorType make_channel_selector_type() {
107 return static_cast<SkDisplacementMapEffect::ChannelSelectorType>(R(4)+1);
108}
109
110static void make_g_bitmap(SkBitmap& bitmap) {
111 bitmap.setConfig(SkBitmap::kARGB_8888_Config, kBitmapSize, kBitmapSize);
112 bitmap.allocPixels();
113 SkBitmapDevice device(bitmap);
114 SkCanvas canvas(&device);
115 canvas.clear(0x00000000);
116 SkPaint paint;
117 paint.setAntiAlias(true);
118 paint.setColor(0xFF884422);
119 paint.setTextSize(SkIntToScalar(kBitmapSize/2));
120 const char* str = "g";
121 canvas.drawText(str, strlen(str), SkIntToScalar(kBitmapSize/8),
122 SkIntToScalar(kBitmapSize/4), paint);
123}
124
125static void make_checkerboard_bitmap(SkBitmap& bitmap) {
126 bitmap.setConfig(SkBitmap::kARGB_8888_Config, kBitmapSize, kBitmapSize);
127 bitmap.allocPixels();
128 SkBitmapDevice device(bitmap);
129 SkCanvas canvas(&device);
130 canvas.clear(0x00000000);
131 SkPaint darkPaint;
132 darkPaint.setColor(0xFF804020);
133 SkPaint lightPaint;
134 lightPaint.setColor(0xFF244484);
135 const int i = kBitmapSize / 8;
136 const SkScalar f = SkIntToScalar(i);
137 for (int y = 0; y < kBitmapSize; y += i) {
138 for (int x = 0; x < kBitmapSize; x += i) {
139 canvas.save();
140 canvas.translate(SkIntToScalar(x), SkIntToScalar(y));
141 canvas.drawRect(SkRect::MakeXYWH(0, 0, f, f), darkPaint);
142 canvas.drawRect(SkRect::MakeXYWH(f, 0, f, f), lightPaint);
143 canvas.drawRect(SkRect::MakeXYWH(0, f, f, f), lightPaint);
144 canvas.drawRect(SkRect::MakeXYWH(f, f, f, f), darkPaint);
145 canvas.restore();
146 }
147 }
148}
149
150static const SkBitmap& make_bitmap() {
151 static SkBitmap bitmap[2];
152 static bool initialized = false;
153 if (!initialized) {
154 make_g_bitmap(bitmap[0]);
155 make_checkerboard_bitmap(bitmap[1]);
156 initialized = true;
157 }
158 return bitmap[R(2)];
159}
160
161static SkImageFilter* make_image_filter(bool canBeNull = true) {
162 SkImageFilter* filter = 0;
163
164 // Add a 1 in 3 chance to get a NULL input
165 if (canBeNull && (R(3) == 1)) { return filter; }
166
167 enum { BICUBIC, MERGE, COLOR, BLUR, MAGNIFIER, XFERMODE, OFFSET, COMPOSE,
168 DISTANT_LIGHT, POINT_LIGHT, SPOT_LIGHT, NOISE, DROP_SHADOW,
commit-bot@chromium.orgcd3b15c2013-12-04 17:06:49 +0000169 MORPHOLOGY, BITMAP, DISPLACE, TILE, NUM_FILTERS };
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +0000170
171 switch (R(NUM_FILTERS)) {
172 case BICUBIC:
173 // Scale is set to 1 here so that it can fit in the DAG without resizing the output
174 filter = SkBicubicImageFilter::CreateMitchell(SkSize::Make(1, 1), make_image_filter());
175 break;
176 case MERGE:
177 filter = new SkMergeImageFilter(make_image_filter(), make_image_filter(), make_xfermode());
178 break;
179 case COLOR:
180 {
181 SkAutoTUnref<SkColorFilter> cf((R(2) == 1) ?
182 SkColorFilter::CreateModeFilter(make_color(), make_xfermode()) :
183 SkColorFilter::CreateLightingFilter(make_color(), make_color()));
184 filter = cf.get() ? SkColorFilterImageFilter::Create(cf, make_image_filter()) : 0;
185 }
186 break;
187 case BLUR:
188 filter = new SkBlurImageFilter(make_scalar(true), make_scalar(true), make_image_filter());
189 break;
190 case MAGNIFIER:
commit-bot@chromium.orgcd3b15c2013-12-04 17:06:49 +0000191 filter = new SkMagnifierImageFilter(make_rect(), make_scalar(true));
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +0000192 break;
193 case XFERMODE:
194 {
195 SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(make_xfermode()));
196 filter = new SkXfermodeImageFilter(mode, make_image_filter(), make_image_filter());
197 }
198 break;
199 case OFFSET:
200 filter = new SkOffsetImageFilter(make_scalar(), make_scalar(), make_image_filter());
201 break;
202 case COMPOSE:
203 filter = new SkComposeImageFilter(make_image_filter(), make_image_filter());
204 break;
205 case DISTANT_LIGHT:
206 filter = (R(2) == 1) ?
207 SkLightingImageFilter::CreateDistantLitDiffuse(make_point(),
208 make_color(), make_scalar(), make_scalar(), make_image_filter()) :
209 SkLightingImageFilter::CreateDistantLitSpecular(make_point(),
210 make_color(), make_scalar(), make_scalar(), SkIntToScalar(R(10)),
211 make_image_filter());
212 break;
213 case POINT_LIGHT:
214 filter = (R(2) == 1) ?
215 SkLightingImageFilter::CreatePointLitDiffuse(make_point(),
216 make_color(), make_scalar(), make_scalar(), make_image_filter()) :
217 SkLightingImageFilter::CreatePointLitSpecular(make_point(),
218 make_color(), make_scalar(), make_scalar(), SkIntToScalar(R(10)),
219 make_image_filter());
220 break;
221 case SPOT_LIGHT:
222 filter = (R(2) == 1) ?
223 SkLightingImageFilter::CreateSpotLitDiffuse(SkPoint3(0, 0, 0),
224 make_point(), make_scalar(), make_scalar(), make_color(),
225 make_scalar(), make_scalar(), make_image_filter()) :
226 SkLightingImageFilter::CreateSpotLitSpecular(SkPoint3(0, 0, 0),
227 make_point(), make_scalar(), make_scalar(), make_color(),
228 make_scalar(), make_scalar(), SkIntToScalar(R(10)), make_image_filter());
229 break;
230 case NOISE:
231 {
232 SkAutoTUnref<SkShader> shader((R(2) == 1) ?
233 SkPerlinNoiseShader::CreateFractalNoise(
sugoi@google.combb8148b2013-09-19 19:51:27 +0000234 make_scalar(true), make_scalar(true), R(10.0f), make_scalar()) :
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +0000235 SkPerlinNoiseShader::CreateTubulence(
sugoi@google.combb8148b2013-09-19 19:51:27 +0000236 make_scalar(true), make_scalar(true), R(10.0f), make_scalar()));
reed@google.com44699382013-10-31 17:28:30 +0000237 SkImageFilter::CropRect cropR(SkRect::MakeWH(SkIntToScalar(kBitmapSize),
238 SkIntToScalar(kBitmapSize)));
239 filter = SkRectShaderImageFilter::Create(shader, &cropR);
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +0000240 }
241 break;
242 case DROP_SHADOW:
243 filter = new SkDropShadowImageFilter(make_scalar(), make_scalar(),
244 make_scalar(true), make_color(), make_image_filter());
245 break;
246 case MORPHOLOGY:
247 if (R(2) == 1)
sugoi@google.combb8148b2013-09-19 19:51:27 +0000248 filter = new SkDilateImageFilter(R(static_cast<float>(kBitmapSize)),
249 R(static_cast<float>(kBitmapSize)), make_image_filter());
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +0000250 else
sugoi@google.combb8148b2013-09-19 19:51:27 +0000251 filter = new SkErodeImageFilter(R(static_cast<float>(kBitmapSize)),
252 R(static_cast<float>(kBitmapSize)), make_image_filter());
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +0000253 break;
254 case BITMAP:
255 filter = new SkBitmapSource(make_bitmap());
256 break;
257 case DISPLACE:
258 filter = new SkDisplacementMapEffect(make_channel_selector_type(),
259 make_channel_selector_type(), make_scalar(),
260 make_image_filter(false), make_image_filter());
261 break;
commit-bot@chromium.orgcd3b15c2013-12-04 17:06:49 +0000262 case TILE:
263 filter = new SkTileImageFilter(make_rect(), make_rect(), make_image_filter(false));
264 break;
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +0000265 default:
266 break;
267 }
268 return (filter || canBeNull) ? filter : make_image_filter(canBeNull);
269}
270
commit-bot@chromium.org77e079a2013-10-28 15:52:02 +0000271static SkImageFilter* make_serialized_image_filter() {
272 SkAutoTUnref<SkImageFilter> filter(make_image_filter(false));
273 SkAutoTUnref<SkData> data(SkValidatingSerializeFlattenable(filter));
274 const unsigned char* ptr = static_cast<const unsigned char*>(data->data());
275 size_t len = data->size();
276#ifdef SK_ADD_RANDOM_BIT_FLIPS
277 unsigned char* p = const_cast<unsigned char*>(ptr);
278 for (size_t i = 0; i < len; ++i, ++p) {
commit-bot@chromium.orgcd3b15c2013-12-04 17:06:49 +0000279 if (R(250) == 1) { // 0.4% of the time, flip a bit or byte
280 if (R(10) == 1) { // Then 10% of the time, change a whole byte
281 switch(R(3)) {
282 case 0:
283 *p ^= 0xFF; // Flip entire byte
284 break;
285 case 1:
286 *p = 0xFF; // Set all bits to 1
287 break;
288 case 2:
289 *p = 0x00; // Set all bits to 0
290 break;
291 }
292 } else {
293 *p ^= (1 << R(8));
294 }
commit-bot@chromium.org77e079a2013-10-28 15:52:02 +0000295 }
296 }
297#endif // SK_ADD_RANDOM_BIT_FLIPS
298 SkFlattenable* flattenable = SkValidatingDeserializeFlattenable(ptr, len,
299 SkImageFilter::GetFlattenableType());
commit-bot@chromium.org77e079a2013-10-28 15:52:02 +0000300 return static_cast<SkImageFilter*>(flattenable);
301}
302
sugoi@google.combb8148b2013-09-19 19:51:27 +0000303static void drawClippedBitmap(SkCanvas* canvas, int x, int y, const SkPaint& paint) {
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +0000304 canvas->save();
305 canvas->clipRect(SkRect::MakeXYWH(SkIntToScalar(x), SkIntToScalar(y),
306 SkIntToScalar(kBitmapSize), SkIntToScalar(kBitmapSize)));
307 canvas->drawBitmap(make_bitmap(), SkIntToScalar(x), SkIntToScalar(y), &paint);
308 canvas->restore();
309}
310
311static void do_fuzz(SkCanvas* canvas) {
commit-bot@chromium.orgcd3b15c2013-12-04 17:06:49 +0000312#ifdef SK_FUZZER_IS_VERBOSE
313 static uint32_t filterId = 0;
314 if (0 == filterId) {
315 printf("Fuzzing with %u\n", kSeed);
316 }
317 printf("Filter no %u\r", filterId);
318 fflush(stdout);
319 filterId++;
320#endif
321
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +0000322 SkPaint paint;
commit-bot@chromium.orgcd3b15c2013-12-04 17:06:49 +0000323 SkSafeUnref(paint.setImageFilter(make_serialized_image_filter()));
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +0000324 drawClippedBitmap(canvas, 0, 0, paint);
325}
326
327//////////////////////////////////////////////////////////////////////////////
328
329class ImageFilterFuzzView : public SampleView {
330public:
331 ImageFilterFuzzView() {
332 this->setBGColor(0xFFDDDDDD);
333 }
334
335protected:
336 // overrides from SkEventSink
337 virtual bool onQuery(SkEvent* evt) {
338 if (SampleCode::TitleQ(*evt)) {
339 SampleCode::TitleR(evt, "ImageFilterFuzzer");
340 return true;
341 }
342 return this->INHERITED::onQuery(evt);
343 }
344
345 void drawBG(SkCanvas* canvas) {
346 canvas->drawColor(0xFFDDDDDD);
347 }
348
349 virtual void onDrawContent(SkCanvas* canvas) {
350 do_fuzz(canvas);
351 this->inval(0);
352 }
353
354private:
355 typedef SkView INHERITED;
356};
357
358//////////////////////////////////////////////////////////////////////////////
359
360static SkView* MyFactory() { return new ImageFilterFuzzView; }
361static SkViewRegister reg(MyFactory);