blob: e31f512c7e352b6b259f3d8b603b7bbf71b15d21 [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.orgc2e9db32013-12-06 20:14:46 +000034//#define SK_ADD_RANDOM_BIT_FLIPS
35//#define SK_FUZZER_IS_VERBOSE
36
commit-bot@chromium.orgcd3b15c2013-12-04 17:06:49 +000037static const uint32_t kSeed = (uint32_t)(time(NULL));
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +000038static SkRandom gRand(kSeed);
39static bool return_large = false;
40static bool return_undef = false;
41
42static const int kBitmapSize = 24;
43
44static int R(float x) {
45 return (int)floor(SkScalarToFloat(gRand.nextUScalar1()) * x);
46}
47
48#if defined _WIN32
49#pragma warning ( push )
50// we are intentionally causing an overflow here
51// (warning C4756: overflow in constant arithmetic)
52#pragma warning ( disable : 4756 )
53#endif
54
55static float huge() {
56 double d = 1e100;
57 float f = (float)d;
58 return f;
59}
60
61#if defined _WIN32
62#pragma warning ( pop )
63#endif
64
65static float make_number(bool positiveOnly) {
66 float f = positiveOnly ? 1.0f : 0.0f;
67 float v = f;
68 int sel;
69
70 if (return_large) sel = R(6); else sel = R(4);
71 if (!return_undef && sel == 0) sel = 1;
72
73 if (R(2) == 1) v = (float)(R(100)+f); else
74
75 switch (sel) {
76 case 0: break;
77 case 1: v = f; break;
78 case 2: v = 0.000001f; break;
79 case 3: v = 10000.0f; break;
80 case 4: v = 2000000000.0f; break;
81 case 5: v = huge(); break;
82 }
83
84 if (!positiveOnly && (R(4) == 1)) v = -v;
85 return v;
86}
87
88static SkScalar make_scalar(bool positiveOnly = false) {
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +000089 return make_number(positiveOnly);
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +000090}
91
commit-bot@chromium.orgcd3b15c2013-12-04 17:06:49 +000092static SkRect make_rect() {
93 return SkRect::MakeWH(SkIntToScalar(R(static_cast<float>(kBitmapSize))),
94 SkIntToScalar(R(static_cast<float>(kBitmapSize))));
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +000095}
96
97static SkXfermode::Mode make_xfermode() {
98 return static_cast<SkXfermode::Mode>(R(SkXfermode::kLastMode+1));
99}
100
101static SkColor make_color() {
102 return (R(2) == 1) ? 0xFFC0F0A0 : 0xFF000090;
103}
104
105static SkPoint3 make_point() {
106 return SkPoint3(make_scalar(), make_scalar(), make_scalar(true));
107}
108
109static SkDisplacementMapEffect::ChannelSelectorType make_channel_selector_type() {
110 return static_cast<SkDisplacementMapEffect::ChannelSelectorType>(R(4)+1);
111}
112
113static void make_g_bitmap(SkBitmap& bitmap) {
commit-bot@chromium.orgef74fa12013-12-17 20:49:46 +0000114 bitmap.setConfig((SkBitmap::Config)R(SkBitmap::kConfigCount), kBitmapSize, kBitmapSize);
115 while (!bitmap.allocPixels()) {
116 bitmap.setConfig((SkBitmap::Config)R(SkBitmap::kConfigCount), kBitmapSize, kBitmapSize);
117 }
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +0000118 SkBitmapDevice device(bitmap);
119 SkCanvas canvas(&device);
120 canvas.clear(0x00000000);
121 SkPaint paint;
122 paint.setAntiAlias(true);
123 paint.setColor(0xFF884422);
124 paint.setTextSize(SkIntToScalar(kBitmapSize/2));
125 const char* str = "g";
126 canvas.drawText(str, strlen(str), SkIntToScalar(kBitmapSize/8),
127 SkIntToScalar(kBitmapSize/4), paint);
128}
129
130static void make_checkerboard_bitmap(SkBitmap& bitmap) {
commit-bot@chromium.orgef74fa12013-12-17 20:49:46 +0000131 bitmap.setConfig((SkBitmap::Config)R(SkBitmap::kConfigCount), kBitmapSize, kBitmapSize);
132 while (!bitmap.allocPixels()) {
133 bitmap.setConfig((SkBitmap::Config)R(SkBitmap::kConfigCount), kBitmapSize, kBitmapSize);
134 }
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +0000135 SkBitmapDevice device(bitmap);
136 SkCanvas canvas(&device);
137 canvas.clear(0x00000000);
138 SkPaint darkPaint;
139 darkPaint.setColor(0xFF804020);
140 SkPaint lightPaint;
141 lightPaint.setColor(0xFF244484);
142 const int i = kBitmapSize / 8;
143 const SkScalar f = SkIntToScalar(i);
144 for (int y = 0; y < kBitmapSize; y += i) {
145 for (int x = 0; x < kBitmapSize; x += i) {
146 canvas.save();
147 canvas.translate(SkIntToScalar(x), SkIntToScalar(y));
148 canvas.drawRect(SkRect::MakeXYWH(0, 0, f, f), darkPaint);
149 canvas.drawRect(SkRect::MakeXYWH(f, 0, f, f), lightPaint);
150 canvas.drawRect(SkRect::MakeXYWH(0, f, f, f), lightPaint);
151 canvas.drawRect(SkRect::MakeXYWH(f, f, f, f), darkPaint);
152 canvas.restore();
153 }
154 }
155}
156
157static const SkBitmap& make_bitmap() {
158 static SkBitmap bitmap[2];
159 static bool initialized = false;
160 if (!initialized) {
161 make_g_bitmap(bitmap[0]);
162 make_checkerboard_bitmap(bitmap[1]);
163 initialized = true;
164 }
165 return bitmap[R(2)];
166}
167
168static SkImageFilter* make_image_filter(bool canBeNull = true) {
169 SkImageFilter* filter = 0;
170
171 // Add a 1 in 3 chance to get a NULL input
172 if (canBeNull && (R(3) == 1)) { return filter; }
173
174 enum { BICUBIC, MERGE, COLOR, BLUR, MAGNIFIER, XFERMODE, OFFSET, COMPOSE,
175 DISTANT_LIGHT, POINT_LIGHT, SPOT_LIGHT, NOISE, DROP_SHADOW,
commit-bot@chromium.orgcd3b15c2013-12-04 17:06:49 +0000176 MORPHOLOGY, BITMAP, DISPLACE, TILE, NUM_FILTERS };
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +0000177
178 switch (R(NUM_FILTERS)) {
179 case BICUBIC:
180 // Scale is set to 1 here so that it can fit in the DAG without resizing the output
181 filter = SkBicubicImageFilter::CreateMitchell(SkSize::Make(1, 1), make_image_filter());
182 break;
183 case MERGE:
184 filter = new SkMergeImageFilter(make_image_filter(), make_image_filter(), make_xfermode());
185 break;
186 case COLOR:
187 {
188 SkAutoTUnref<SkColorFilter> cf((R(2) == 1) ?
189 SkColorFilter::CreateModeFilter(make_color(), make_xfermode()) :
190 SkColorFilter::CreateLightingFilter(make_color(), make_color()));
191 filter = cf.get() ? SkColorFilterImageFilter::Create(cf, make_image_filter()) : 0;
192 }
193 break;
194 case BLUR:
195 filter = new SkBlurImageFilter(make_scalar(true), make_scalar(true), make_image_filter());
196 break;
197 case MAGNIFIER:
commit-bot@chromium.orgcd3b15c2013-12-04 17:06:49 +0000198 filter = new SkMagnifierImageFilter(make_rect(), make_scalar(true));
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +0000199 break;
200 case XFERMODE:
201 {
202 SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(make_xfermode()));
203 filter = new SkXfermodeImageFilter(mode, make_image_filter(), make_image_filter());
204 }
205 break;
206 case OFFSET:
207 filter = new SkOffsetImageFilter(make_scalar(), make_scalar(), make_image_filter());
208 break;
209 case COMPOSE:
210 filter = new SkComposeImageFilter(make_image_filter(), make_image_filter());
211 break;
212 case DISTANT_LIGHT:
213 filter = (R(2) == 1) ?
214 SkLightingImageFilter::CreateDistantLitDiffuse(make_point(),
215 make_color(), make_scalar(), make_scalar(), make_image_filter()) :
216 SkLightingImageFilter::CreateDistantLitSpecular(make_point(),
217 make_color(), make_scalar(), make_scalar(), SkIntToScalar(R(10)),
218 make_image_filter());
219 break;
220 case POINT_LIGHT:
221 filter = (R(2) == 1) ?
222 SkLightingImageFilter::CreatePointLitDiffuse(make_point(),
223 make_color(), make_scalar(), make_scalar(), make_image_filter()) :
224 SkLightingImageFilter::CreatePointLitSpecular(make_point(),
225 make_color(), make_scalar(), make_scalar(), SkIntToScalar(R(10)),
226 make_image_filter());
227 break;
228 case SPOT_LIGHT:
229 filter = (R(2) == 1) ?
230 SkLightingImageFilter::CreateSpotLitDiffuse(SkPoint3(0, 0, 0),
231 make_point(), make_scalar(), make_scalar(), make_color(),
232 make_scalar(), make_scalar(), make_image_filter()) :
233 SkLightingImageFilter::CreateSpotLitSpecular(SkPoint3(0, 0, 0),
234 make_point(), make_scalar(), make_scalar(), make_color(),
235 make_scalar(), make_scalar(), SkIntToScalar(R(10)), make_image_filter());
236 break;
237 case NOISE:
238 {
239 SkAutoTUnref<SkShader> shader((R(2) == 1) ?
240 SkPerlinNoiseShader::CreateFractalNoise(
sugoi@google.combb8148b2013-09-19 19:51:27 +0000241 make_scalar(true), make_scalar(true), R(10.0f), make_scalar()) :
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +0000242 SkPerlinNoiseShader::CreateTubulence(
sugoi@google.combb8148b2013-09-19 19:51:27 +0000243 make_scalar(true), make_scalar(true), R(10.0f), make_scalar()));
reed@google.com44699382013-10-31 17:28:30 +0000244 SkImageFilter::CropRect cropR(SkRect::MakeWH(SkIntToScalar(kBitmapSize),
245 SkIntToScalar(kBitmapSize)));
246 filter = SkRectShaderImageFilter::Create(shader, &cropR);
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +0000247 }
248 break;
249 case DROP_SHADOW:
250 filter = new SkDropShadowImageFilter(make_scalar(), make_scalar(),
251 make_scalar(true), make_color(), make_image_filter());
252 break;
253 case MORPHOLOGY:
commit-bot@chromium.org43f4a552014-01-15 20:20:24 +0000254 if (R(2) == 1) {
sugoi@google.combb8148b2013-09-19 19:51:27 +0000255 filter = new SkDilateImageFilter(R(static_cast<float>(kBitmapSize)),
256 R(static_cast<float>(kBitmapSize)), make_image_filter());
commit-bot@chromium.org43f4a552014-01-15 20:20:24 +0000257 } else {
sugoi@google.combb8148b2013-09-19 19:51:27 +0000258 filter = new SkErodeImageFilter(R(static_cast<float>(kBitmapSize)),
259 R(static_cast<float>(kBitmapSize)), make_image_filter());
commit-bot@chromium.org43f4a552014-01-15 20:20:24 +0000260 }
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +0000261 break;
262 case BITMAP:
commit-bot@chromium.org43f4a552014-01-15 20:20:24 +0000263 if (R(2) == 1) {
264 filter = new SkBitmapSource(make_bitmap(), make_rect(), make_rect());
265 } else {
266 filter = new SkBitmapSource(make_bitmap());
267 }
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +0000268 break;
269 case DISPLACE:
270 filter = new SkDisplacementMapEffect(make_channel_selector_type(),
271 make_channel_selector_type(), make_scalar(),
272 make_image_filter(false), make_image_filter());
273 break;
commit-bot@chromium.orgcd3b15c2013-12-04 17:06:49 +0000274 case TILE:
275 filter = new SkTileImageFilter(make_rect(), make_rect(), make_image_filter(false));
276 break;
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +0000277 default:
278 break;
279 }
280 return (filter || canBeNull) ? filter : make_image_filter(canBeNull);
281}
282
commit-bot@chromium.org77e079a2013-10-28 15:52:02 +0000283static SkImageFilter* make_serialized_image_filter() {
284 SkAutoTUnref<SkImageFilter> filter(make_image_filter(false));
285 SkAutoTUnref<SkData> data(SkValidatingSerializeFlattenable(filter));
286 const unsigned char* ptr = static_cast<const unsigned char*>(data->data());
287 size_t len = data->size();
288#ifdef SK_ADD_RANDOM_BIT_FLIPS
289 unsigned char* p = const_cast<unsigned char*>(ptr);
290 for (size_t i = 0; i < len; ++i, ++p) {
commit-bot@chromium.orgcd3b15c2013-12-04 17:06:49 +0000291 if (R(250) == 1) { // 0.4% of the time, flip a bit or byte
292 if (R(10) == 1) { // Then 10% of the time, change a whole byte
293 switch(R(3)) {
294 case 0:
295 *p ^= 0xFF; // Flip entire byte
296 break;
297 case 1:
298 *p = 0xFF; // Set all bits to 1
299 break;
300 case 2:
301 *p = 0x00; // Set all bits to 0
302 break;
303 }
304 } else {
305 *p ^= (1 << R(8));
306 }
commit-bot@chromium.org77e079a2013-10-28 15:52:02 +0000307 }
308 }
309#endif // SK_ADD_RANDOM_BIT_FLIPS
310 SkFlattenable* flattenable = SkValidatingDeserializeFlattenable(ptr, len,
311 SkImageFilter::GetFlattenableType());
commit-bot@chromium.org77e079a2013-10-28 15:52:02 +0000312 return static_cast<SkImageFilter*>(flattenable);
313}
314
sugoi@google.combb8148b2013-09-19 19:51:27 +0000315static void drawClippedBitmap(SkCanvas* canvas, int x, int y, const SkPaint& paint) {
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +0000316 canvas->save();
317 canvas->clipRect(SkRect::MakeXYWH(SkIntToScalar(x), SkIntToScalar(y),
318 SkIntToScalar(kBitmapSize), SkIntToScalar(kBitmapSize)));
319 canvas->drawBitmap(make_bitmap(), SkIntToScalar(x), SkIntToScalar(y), &paint);
320 canvas->restore();
321}
322
323static void do_fuzz(SkCanvas* canvas) {
commit-bot@chromium.orgef74fa12013-12-17 20:49:46 +0000324 SkImageFilter* filter = make_serialized_image_filter();
325
commit-bot@chromium.orgcd3b15c2013-12-04 17:06:49 +0000326#ifdef SK_FUZZER_IS_VERBOSE
commit-bot@chromium.orgef74fa12013-12-17 20:49:46 +0000327 static uint32_t numFilters = 0;
328 static uint32_t numValidFilters = 0;
329 if (0 == numFilters) {
commit-bot@chromium.orgcd3b15c2013-12-04 17:06:49 +0000330 printf("Fuzzing with %u\n", kSeed);
331 }
commit-bot@chromium.orgef74fa12013-12-17 20:49:46 +0000332 numFilters++;
333 if (NULL != filter) {
334 numValidFilters++;
335 }
336 printf("Filter no : %u. Valid filters so far : %u\r", numFilters, numValidFilters);
commit-bot@chromium.orgcd3b15c2013-12-04 17:06:49 +0000337 fflush(stdout);
commit-bot@chromium.orgcd3b15c2013-12-04 17:06:49 +0000338#endif
339
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +0000340 SkPaint paint;
commit-bot@chromium.orgef74fa12013-12-17 20:49:46 +0000341 SkSafeUnref(paint.setImageFilter(filter));
commit-bot@chromium.org22d69f92013-09-19 18:40:49 +0000342 drawClippedBitmap(canvas, 0, 0, paint);
343}
344
345//////////////////////////////////////////////////////////////////////////////
346
347class ImageFilterFuzzView : public SampleView {
348public:
349 ImageFilterFuzzView() {
350 this->setBGColor(0xFFDDDDDD);
351 }
352
353protected:
354 // overrides from SkEventSink
355 virtual bool onQuery(SkEvent* evt) {
356 if (SampleCode::TitleQ(*evt)) {
357 SampleCode::TitleR(evt, "ImageFilterFuzzer");
358 return true;
359 }
360 return this->INHERITED::onQuery(evt);
361 }
362
363 void drawBG(SkCanvas* canvas) {
364 canvas->drawColor(0xFFDDDDDD);
365 }
366
367 virtual void onDrawContent(SkCanvas* canvas) {
368 do_fuzz(canvas);
369 this->inval(0);
370 }
371
372private:
373 typedef SkView INHERITED;
374};
375
376//////////////////////////////////////////////////////////////////////////////
377
378static SkView* MyFactory() { return new ImageFilterFuzzView; }
379static SkViewRegister reg(MyFactory);