1 /*
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 "Fuzz.h"
8 #include "Sk1DPathEffect.h"
9 #include "Sk2DPathEffect.h"
10 #include "SkAlphaThresholdFilter.h"
11 #include "SkArcToPathEffect.h"
12 #include "SkBlurImageFilter.h"
13 #include "SkBlurMaskFilter.h"
14 #include "SkCanvas.h"
15 #include "SkColorFilter.h"
16 #include "SkColorFilterImageFilter.h"
17 #include "SkColorMatrixFilter.h"
18 #include "SkComposeImageFilter.h"
19 #include "SkCornerPathEffect.h"
20 #include "SkDashPathEffect.h"
21 #include "SkData.h"
22 #include "SkDiscretePathEffect.h"
23 #include "SkDisplacementMapEffect.h"
24 #include "SkDropShadowImageFilter.h"
25 #include "SkEmbossMaskFilter.h"
26 #include "SkFlattenableSerialization.h"
27 #include "SkImageSource.h"
28 #include "SkLayerRasterizer.h"
29 #include "SkLightingImageFilter.h"
30 #include "SkLumaColorFilter.h"
31 #include "SkMagnifierImageFilter.h"
32 #include "SkMatrixConvolutionImageFilter.h"
33 #include "SkMergeImageFilter.h"
34 #include "SkMorphologyImageFilter.h"
35 #include "SkOffsetImageFilter.h"
36 #include "SkPaintImageFilter.h"
37 #include "SkPerlinNoiseShader.h"
38 #include "SkPictureImageFilter.h"
39 #include "SkPictureRecorder.h"
40 #include "SkPoint3.h"
41 #include "SkRandom.h"
42 #include "SkTableColorFilter.h"
43 #include "SkTileImageFilter.h"
44 #include "SkTypeface.h"
45 #include "SkXfermodeImageFilter.h"
46 #include <cmath>
47 #include <stdio.h>
48 #include <time.h>
49 
50 #define SK_ADD_RANDOM_BIT_FLIPS
51 
52 static Fuzz* fuzz;
53 static const int kBitmapSize = 24;
54 
55 
56 // There should be no more than one make_* used as a function argument.
make_bool()57 static bool make_bool() {
58     bool b; fuzz->next(&b);
59     return b;
60 }
61 
make_number(bool positiveOnly)62 static float make_number(bool positiveOnly) {
63     float f;
64     fuzz->next(&f);
65     if (positiveOnly) {
66         return std::abs(f);
67     }
68     return f;
69 }
70 
make_string()71 static SkString make_string() {
72     int length;
73     fuzz->nextRange(&length, 0, 1000);
74     SkString str(length);
75     for (int i = 0; i < length; ++i) {
76         char c;
77         fuzz->nextRange(&c, 0, 255);
78         str[i] = c;
79     }
80     return str;
81 }
82 
make_font_name()83 static SkString make_font_name() {
84     int sel;
85     fuzz->nextRange(&sel, 0, 7);
86 
87     switch(sel) {
88         case 0: return SkString("Courier New");
89         case 1: return SkString("Helvetica");
90         case 2: return SkString("monospace");
91         case 3: return SkString("sans-serif");
92         case 4: return SkString("serif");
93         case 5: return SkString("Times");
94         case 6: return SkString("Times New Roman");
95         case 7:
96         default:
97             return make_string();
98     }
99 }
100 
make_rect()101 static SkRect make_rect() {
102     SkScalar w, h;
103     fuzz->nextRange(&w, 0.0f, (float) kBitmapSize-1);
104     fuzz->nextRange(&h, 0.0f, (float) kBitmapSize-1);
105     return SkRect::MakeWH(w, h);
106 }
107 
make_region()108 static SkRegion make_region() {
109     int32_t x, y, w, h;
110     fuzz->nextRange(&x, 0, kBitmapSize-1);
111     fuzz->nextRange(&y, 0, kBitmapSize-1);
112     fuzz->nextRange(&w, 0, kBitmapSize-1);
113     fuzz->nextRange(&h, 0, kBitmapSize-1);
114     SkIRect iRegion = SkIRect::MakeXYWH(x,y,w,h);
115     return SkRegion(iRegion);
116 }
117 
init_matrix(SkMatrix * m)118 static void init_matrix(SkMatrix* m) {
119     SkScalar mat[9];
120     fuzz->nextN(mat, 9);
121     m->set9(mat);
122 }
123 
make_blendmode()124 static SkBlendMode make_blendmode() {
125     uint8_t i;
126     fuzz->nextRange(&i, 0, (uint8_t)SkBlendMode::kLastMode);
127     return static_cast<SkBlendMode>(i);
128 }
129 
make_paint_align()130 static SkPaint::Align make_paint_align() {
131     uint8_t i;
132     fuzz->nextRange(&i, 0, (uint8_t)SkPaint::kRight_Align);
133     return static_cast<SkPaint::Align>(i);
134 }
135 
make_paint_hinting()136 static SkPaint::Hinting make_paint_hinting() {
137     uint8_t i;
138     fuzz->nextRange(&i, 0, (uint8_t)SkPaint::kFull_Hinting);
139     return static_cast<SkPaint::Hinting>(i);
140 }
141 
make_paint_style()142 static SkPaint::Style make_paint_style() {
143     uint8_t i;
144     fuzz->nextRange(&i, 0, (uint8_t)SkPaint::kStrokeAndFill_Style);
145     return static_cast<SkPaint::Style>(i);
146 }
147 
make_paint_cap()148 static SkPaint::Cap make_paint_cap() {
149     uint8_t i;
150     fuzz->nextRange(&i, 0, (uint8_t)SkPaint::kDefault_Cap);
151     return static_cast<SkPaint::Cap>(i);
152 }
153 
make_paint_join()154 static SkPaint::Join make_paint_join() {
155     uint8_t i;
156     fuzz->nextRange(&i, 0, (uint8_t)SkPaint::kDefault_Join);
157     return static_cast<SkPaint::Join>(i);
158 }
159 
make_paint_text_encoding()160 static SkPaint::TextEncoding make_paint_text_encoding() {
161     uint8_t i;
162     fuzz->nextRange(&i, 0, (uint8_t)SkPaint::kGlyphID_TextEncoding);
163     return static_cast<SkPaint::TextEncoding>(i);
164 }
165 
make_blur_style()166 static SkBlurStyle make_blur_style() {
167     uint8_t i;
168     fuzz->nextRange(&i, 0, (uint8_t)kLastEnum_SkBlurStyle);
169     return static_cast<SkBlurStyle>(i);
170 }
171 
make_blur_mask_filter_flag()172 static SkBlurMaskFilter::BlurFlags make_blur_mask_filter_flag() {
173     uint8_t i;
174     fuzz->nextRange(&i, 0, (uint8_t)SkBlurMaskFilter::kAll_BlurFlag);
175     return static_cast<SkBlurMaskFilter::BlurFlags>(i);
176 }
177 
make_filter_quality()178 static SkFilterQuality make_filter_quality() {
179     uint8_t i;
180     fuzz->nextRange(&i, 0, (uint8_t)kHigh_SkFilterQuality);
181     return static_cast<SkFilterQuality>(i);
182 }
183 
make_typeface_style()184 static SkFontStyle make_typeface_style() {
185     uint8_t i;
186     fuzz->nextRange(&i, 0, (uint8_t)SkTypeface::kBoldItalic);
187     return SkFontStyle::FromOldStyle(i);
188 }
189 
make_path_1d_path_effect_style()190 static SkPath1DPathEffect::Style make_path_1d_path_effect_style() {
191     uint8_t i;
192     fuzz->nextRange(&i, 0, (uint8_t)SkPath1DPathEffect::kLastEnum_Style);
193     return static_cast<SkPath1DPathEffect::Style>(i);
194 }
195 
make_color()196 static SkColor make_color() {
197     return make_bool() ? 0xFFC0F0A0 : 0xFF000090;
198 }
199 
make_shadow_mode()200 static SkDropShadowImageFilter::ShadowMode make_shadow_mode() {
201     return make_bool() ? SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode :
202                         SkDropShadowImageFilter::kDrawShadowOnly_ShadowMode;
203 }
204 
make_point()205 static SkPoint3 make_point() {
206     SkScalar a, b, c;
207     fuzz->next(&a, &b, &c);
208     c = std::abs(c);
209     return SkPoint3::Make(a, b, c);
210 }
211 
make_channel_selector_type()212 static SkDisplacementMapEffect::ChannelSelectorType make_channel_selector_type() {
213     uint8_t i;
214     fuzz->nextRange(&i, 1, (uint8_t)SkDisplacementMapEffect::kA_ChannelSelectorType);
215     return static_cast<SkDisplacementMapEffect::ChannelSelectorType>(i);
216 }
217 
rand_colortype()218 static SkColorType rand_colortype() {
219     uint8_t i;
220     fuzz->nextRange(&i, 0, kLastEnum_SkColorType);
221     return (SkColorType) i;
222 }
223 
rand_bitmap_for_canvas(SkBitmap * bitmap)224 static void rand_bitmap_for_canvas(SkBitmap* bitmap) {
225     SkImageInfo info = SkImageInfo::Make(kBitmapSize, kBitmapSize, rand_colortype(),
226                                  kPremul_SkAlphaType);
227     if (!bitmap->tryAllocPixels(info)){
228         SkDebugf("Bitmap not allocated\n");
229     }
230 }
231 
make_g_bitmap(SkBitmap & bitmap)232 static void make_g_bitmap(SkBitmap& bitmap) {
233     rand_bitmap_for_canvas(&bitmap);
234 
235     SkCanvas canvas(bitmap);
236     canvas.clear(0x00000000);
237     SkPaint paint;
238     paint.setAntiAlias(true);
239     paint.setColor(0xFF884422);
240     paint.setTextSize(SkIntToScalar(kBitmapSize/2));
241     const char* str = "g";
242     canvas.drawText(str, strlen(str), SkIntToScalar(kBitmapSize/8),
243                     SkIntToScalar(kBitmapSize/4), paint);
244 }
245 
make_checkerboard_bitmap(SkBitmap & bitmap)246 static void make_checkerboard_bitmap(SkBitmap& bitmap) {
247     rand_bitmap_for_canvas(&bitmap);
248 
249     SkCanvas canvas(bitmap);
250     canvas.clear(0x00000000);
251     SkPaint darkPaint;
252     darkPaint.setColor(0xFF804020);
253     SkPaint lightPaint;
254     lightPaint.setColor(0xFF244484);
255     const int i = kBitmapSize / 8;
256     const SkScalar f = SkIntToScalar(i);
257     for (int y = 0; y < kBitmapSize; y += i) {
258         for (int x = 0; x < kBitmapSize; x += i) {
259             canvas.save();
260             canvas.translate(SkIntToScalar(x), SkIntToScalar(y));
261             canvas.drawRect(SkRect::MakeXYWH(0, 0, f, f), darkPaint);
262             canvas.drawRect(SkRect::MakeXYWH(f, 0, f, f), lightPaint);
263             canvas.drawRect(SkRect::MakeXYWH(0, f, f, f), lightPaint);
264             canvas.drawRect(SkRect::MakeXYWH(f, f, f, f), darkPaint);
265             canvas.restore();
266         }
267     }
268 }
269 
make_bitmap()270 static const SkBitmap& make_bitmap() {
271     static SkBitmap bitmap[2];
272     static bool initialized = false;
273     if (!initialized) {
274         make_g_bitmap(bitmap[0]);
275         make_checkerboard_bitmap(bitmap[1]);
276         initialized = true;
277     }
278     uint8_t i;
279     fuzz->nextRange(&i, 0, 1);
280     return bitmap[i];
281 }
282 
make_3Dlut(int * cubeDimension,bool invR,bool invG,bool invB)283 static sk_sp<SkData> make_3Dlut(int* cubeDimension, bool invR, bool invG, bool invB) {
284     uint8_t shift;
285     fuzz->nextRange(&shift, 0, 4);
286     int size = 4 << shift;
287     auto data = SkData::MakeUninitialized(sizeof(SkColor) * size * size * size);
288     SkColor* pixels = (SkColor*)(data->writable_data());
289     SkAutoTMalloc<uint8_t> lutMemory(size);
290     SkAutoTMalloc<uint8_t> invLutMemory(size);
291     uint8_t* lut = lutMemory.get();
292     uint8_t* invLut = invLutMemory.get();
293     const int maxIndex = size - 1;
294     for (int i = 0; i < size; i++) {
295         lut[i] = (i * 255) / maxIndex;
296         invLut[i] = ((maxIndex - i) * 255) / maxIndex;
297     }
298     for (int r = 0; r < size; ++r) {
299         for (int g = 0; g < size; ++g) {
300             for (int b = 0; b < size; ++b) {
301                 pixels[(size * ((size * b) + g)) + r] = SkColorSetARGB(0xFF,
302                         invR ? invLut[r] : lut[r],
303                         invG ? invLut[g] : lut[g],
304                         invB ? invLut[b] : lut[b]);
305             }
306         }
307     }
308     if (cubeDimension) {
309         *cubeDimension = size;
310     }
311     return data;
312 }
313 
drawSomething(SkCanvas * canvas)314 static void drawSomething(SkCanvas* canvas) {
315     SkPaint paint;
316 
317     canvas->save();
318     canvas->scale(0.5f, 0.5f);
319     canvas->drawBitmap(make_bitmap(), 0, 0, nullptr);
320     canvas->restore();
321 
322     paint.setAntiAlias(true);
323 
324     paint.setColor(SK_ColorRED);
325     canvas->drawCircle(SkIntToScalar(kBitmapSize/2), SkIntToScalar(kBitmapSize/2), SkIntToScalar(kBitmapSize/3), paint);
326     paint.setColor(SK_ColorBLACK);
327     paint.setTextSize(SkIntToScalar(kBitmapSize/3));
328     canvas->drawText("Picture", 7, SkIntToScalar(kBitmapSize/2), SkIntToScalar(kBitmapSize/4), paint);
329 }
330 
make_color_filter()331 static sk_sp<SkColorFilter> make_color_filter() {
332     uint8_t s;
333     fuzz->nextRange(&s, 0, 5);
334     switch (s) {
335         case 0: {
336             SkScalar array[20];
337             fuzz->nextN(array, 20);
338             return SkColorFilter::MakeMatrixFilterRowMajor255(array);
339         }
340         case 1:
341             return SkLumaColorFilter::Make();
342         case 2: {
343             uint8_t tableA[256];
344             uint8_t tableR[256];
345             uint8_t tableG[256];
346             uint8_t tableB[256];
347             fuzz->nextN(tableA, 256);
348             fuzz->nextN(tableR, 256);
349             fuzz->nextN(tableG, 256);
350             fuzz->nextN(tableB, 256);
351             return SkTableColorFilter::MakeARGB(tableA, tableR, tableG, tableB);
352         }
353         case 3: {
354             SkColor c = make_color();
355             SkBlendMode mode = make_blendmode();
356             return SkColorFilter::MakeModeFilter(c, mode);
357         }
358         case 4: {
359             SkColor a = make_color();
360             SkColor b = make_color();
361             return SkColorMatrixFilter::MakeLightingFilter(a, b);
362         }
363         case 5:
364         default:
365             break;
366     }
367     return nullptr;
368 }
369 
make_path()370 static SkPath make_path() {
371     SkPath path;
372     uint8_t numOps;
373     fuzz->nextRange(&numOps, 0, 30);
374     for (uint8_t i = 0; i < numOps; ++i) {
375         uint8_t op;
376         fuzz->nextRange(&op, 0, 5);
377         SkScalar a, b, c, d, e, f;
378         switch (op) {
379             case 0:
380                 fuzz->next(&a, &b);
381                 path.moveTo(a, b);
382                 break;
383             case 1:
384                 fuzz->next(&a, &b);
385                 path.lineTo(a, b);
386                 break;
387             case 2:
388                 fuzz->next(&a, &b, &c, &d);
389                 path.quadTo(a, b, c, d);
390                 break;
391             case 3:
392                 fuzz->next(&a, &b, &c, &d, &e);
393                 path.conicTo(a, b, c, d, e);
394                 break;
395             case 4:
396                 fuzz->next(&a, &b, &c, &d, &e, &f);
397                 path.cubicTo(a, b, c, d, e, f);
398                 break;
399             case 5:
400             default:
401                 fuzz->next(&a, &b, &c, &d, &e);
402                 path.arcTo(a, b, c, d, e);
403                 break;
404         }
405     }
406     path.close();
407     return path;
408 }
409 
make_path_effect(bool canBeNull=true)410 static sk_sp<SkPathEffect> make_path_effect(bool canBeNull = true) {
411     sk_sp<SkPathEffect> pathEffect;
412     uint8_t s;
413     fuzz->nextRange(&s, 0, 2);
414     if (canBeNull && s == 0) { return pathEffect; }
415 
416     fuzz->nextRange(&s, 0, 8);
417 
418     switch (s) {
419         case 0: {
420             SkScalar a = make_number(true);
421             pathEffect = SkArcToPathEffect::Make(a);
422             break;
423         }
424         case 1: {
425             sk_sp<SkPathEffect> a = make_path_effect(false);
426             sk_sp<SkPathEffect> b = make_path_effect(false);
427             pathEffect = SkPathEffect::MakeCompose(a, b);
428             break;
429         }
430         case 2: {
431             SkScalar a = make_number(false);
432             pathEffect = SkCornerPathEffect::Make(a);
433             break;
434         }
435         case 3: {
436             uint8_t count;
437             fuzz->nextRange(&count, 0, 9);
438             SkScalar intervals[10];
439             fuzz->nextN(intervals, 10);
440             SkScalar a = make_number(false);
441             pathEffect = SkDashPathEffect::Make(intervals, count, a);
442             break;
443         }
444         case 4: {
445             SkScalar a, b;
446             fuzz->next(&a, &b);
447             pathEffect = SkDiscretePathEffect::Make(a, b);
448             break;
449         }
450         case 5: {
451             SkPath path = make_path();
452             SkScalar a, b;
453             fuzz->next(&a, &b);
454             SkPath1DPathEffect::Style style = make_path_1d_path_effect_style();
455             pathEffect = SkPath1DPathEffect::Make(path, a, b, style);
456             break;
457         }
458         case 6: {
459             SkScalar a = make_number(false);
460             SkMatrix m;
461             init_matrix(&m);
462             pathEffect = SkLine2DPathEffect::Make(a, m);
463             break;
464         }
465         case 7: {
466             SkPath path = make_path();
467             SkMatrix m;
468             init_matrix(&m);
469             pathEffect = SkPath2DPathEffect::Make(m, path);
470             break;
471         }
472         case 8:
473         default: {
474             sk_sp<SkPathEffect> a = make_path_effect(false);
475             sk_sp<SkPathEffect> b = make_path_effect(false);
476             pathEffect = SkPathEffect::MakeCompose(a, b);
477             break;
478         }
479     }
480     return pathEffect;
481 }
482 
make_mask_filter()483 static sk_sp<SkMaskFilter> make_mask_filter() {
484     sk_sp<SkMaskFilter> maskFilter;
485     uint8_t s;
486     fuzz->nextRange(&s, 0, 2);
487     switch (s) {
488         case 0: {
489             SkBlurStyle blur = make_blur_style();
490             SkScalar a = make_number(false);
491             SkBlurMaskFilter::BlurFlags flags = make_blur_mask_filter_flag();
492             maskFilter = SkBlurMaskFilter::Make(blur, a, flags);
493             break;
494         }
495         case 1: {
496             SkScalar a = make_number(false);
497             SkEmbossMaskFilter::Light light;
498             fuzz->nextN(light.fDirection, 3);
499             fuzz->nextRange(&light.fPad, 0, 65535);
500             fuzz->nextRange(&light.fAmbient, 0, 255);
501             fuzz->nextRange(&light.fSpecular, 0, 255);
502             maskFilter = SkEmbossMaskFilter::Make(a, light);
503             break;
504         }
505         case 2:
506         default:
507             break;
508     }
509     return maskFilter;
510 }
511 
512 static sk_sp<SkImageFilter> make_image_filter(bool canBeNull = true);
513 
make_paint()514 static SkPaint make_paint() {
515     SkPaint paint;
516     if (fuzz->exhausted()) {
517         return paint;
518     }
519     paint.setHinting(make_paint_hinting());
520     paint.setAntiAlias(make_bool());
521     paint.setDither(make_bool());
522     paint.setLinearText(make_bool());
523     paint.setSubpixelText(make_bool());
524     paint.setLCDRenderText(make_bool());
525     paint.setEmbeddedBitmapText(make_bool());
526     paint.setAutohinted(make_bool());
527     paint.setVerticalText(make_bool());
528     paint.setFakeBoldText(make_bool());
529     paint.setDevKernText(make_bool());
530     paint.setFilterQuality(make_filter_quality());
531     paint.setStyle(make_paint_style());
532     paint.setColor(make_color());
533     paint.setStrokeWidth(make_number(false));
534     paint.setStrokeMiter(make_number(false));
535     paint.setStrokeCap(make_paint_cap());
536     paint.setStrokeJoin(make_paint_join());
537     paint.setColorFilter(make_color_filter());
538     paint.setBlendMode(make_blendmode());
539     paint.setPathEffect(make_path_effect());
540     paint.setMaskFilter(make_mask_filter());
541 
542     if (false) {
543         // our validating buffer does not support typefaces yet, so skip this for now
544         paint.setTypeface(SkTypeface::MakeFromName(make_font_name().c_str(),make_typeface_style()));
545     }
546 
547     SkLayerRasterizer::Builder rasterizerBuilder;
548     SkPaint paintForRasterizer;
549     if (make_bool()) {
550         paintForRasterizer = make_paint();
551     }
552     rasterizerBuilder.addLayer(paintForRasterizer);
553     paint.setRasterizer(rasterizerBuilder.detach());
554     paint.setImageFilter(make_image_filter());
555     bool a, b, c;
556     fuzz->next(&a, &b, &c);
557     sk_sp<SkData> data(make_3Dlut(nullptr, a, b, c));
558     paint.setTextAlign(make_paint_align());
559     SkScalar d, e, f;
560     fuzz->next(&d, &e, &f);
561     paint.setTextSize(d);
562     paint.setTextScaleX(e);
563     paint.setTextSkewX(f);
564     paint.setTextEncoding(make_paint_text_encoding());
565     return paint;
566 }
567 
make_image_filter(bool canBeNull)568 static sk_sp<SkImageFilter> make_image_filter(bool canBeNull) {
569     sk_sp<SkImageFilter> filter;
570 
571     // Add a 1 in 3 chance to get a nullptr input
572     uint8_t i;
573     fuzz->nextRange(&i, 0, 2);
574     if (fuzz->exhausted() || (canBeNull && i == 1)) {
575         return filter;
576     }
577 
578     enum { ALPHA_THRESHOLD, MERGE, COLOR, BLUR, MAGNIFIER,
579            BLENDMODE, OFFSET, MATRIX, MATRIX_CONVOLUTION, COMPOSE,
580            DISTANT_LIGHT, POINT_LIGHT, SPOT_LIGHT, NOISE, DROP_SHADOW,
581            MORPHOLOGY, BITMAP, DISPLACE, TILE, PICTURE, PAINT, NUM_FILTERS };
582 
583     uint8_t s;
584     fuzz->nextRange(&s, 0, NUM_FILTERS - 1);
585     switch (s) {
586     case ALPHA_THRESHOLD: {
587         SkRegion reg = make_region();
588         SkScalar innerMin, outerMax;
589         fuzz->next(&innerMin, &outerMax);
590         sk_sp<SkImageFilter> fil = make_image_filter();
591         filter = SkAlphaThresholdFilter::Make(reg, innerMin, outerMax, fil);
592         break;
593     }
594     case MERGE: {
595         sk_sp<SkImageFilter> filA = make_image_filter();
596         sk_sp<SkImageFilter> filB = make_image_filter();
597         SkBlendMode blend = make_blendmode();
598         filter = SkMergeImageFilter::Make(filA, filB, blend);
599         break;
600     }
601     case COLOR: {
602         sk_sp<SkColorFilter> cf(make_color_filter());
603         filter = cf ? SkColorFilterImageFilter::Make(std::move(cf), make_image_filter())
604                     : nullptr;
605         break;
606     }
607     case BLUR: {
608         SkScalar sX = make_number(true);
609         SkScalar sY = make_number(true);
610         sk_sp<SkImageFilter> fil = make_image_filter();
611 
612         filter = SkBlurImageFilter::Make(sX, sY, fil);
613         break;
614     }
615     case MAGNIFIER: {
616         SkRect rect = make_rect();
617         SkScalar inset = make_number(true);
618         sk_sp<SkImageFilter> fil = make_image_filter();
619         filter = SkMagnifierImageFilter::Make(rect, inset, fil);
620         break;
621     }
622     case BLENDMODE: {
623         SkBlendMode mode = make_blendmode();
624         sk_sp<SkImageFilter> filA = make_image_filter();
625         sk_sp<SkImageFilter> filB = make_image_filter();
626         filter = SkXfermodeImageFilter::Make(mode, filA, filB, nullptr);
627         break;
628     }
629     case OFFSET: {
630         SkScalar dx, dy;
631         fuzz->next(&dx, &dy);
632         sk_sp<SkImageFilter> fil = make_image_filter();
633         filter = SkOffsetImageFilter::Make(dx, dy, fil);
634         break;
635     }
636     case MATRIX: {
637         SkMatrix m;
638         init_matrix(&m);
639         int qual;
640         fuzz->nextRange(&qual, 0, SkFilterQuality::kLast_SkFilterQuality - 1);
641         sk_sp<SkImageFilter> fil = make_image_filter();
642         filter = SkImageFilter::MakeMatrixFilter(m, (SkFilterQuality)qual, fil);
643         break;
644     }
645     case MATRIX_CONVOLUTION: {
646         SkImageFilter::CropRect cropR(SkRect::MakeWH(SkIntToScalar(kBitmapSize),
647                                                      SkIntToScalar(kBitmapSize)));
648         int w, h;
649         fuzz->nextRange(&w, 1, 10);
650         fuzz->nextRange(&h, 1, 10);
651         SkISize size = SkISize::Make(w, h);
652         int arraySize = size.width() * size.height();
653         SkTArray<SkScalar> kernel(arraySize);
654         for (int i = 0; i < arraySize; ++i) {
655             kernel.push_back() = make_number(false);
656         }
657         fuzz->nextRange(&w, 0, size.width()  - 1);
658         fuzz->nextRange(&h, 0, size.height() - 1);
659         SkIPoint kernelOffset = SkIPoint::Make(w, h);
660         int mode;
661         fuzz->nextRange(&mode, 0, SkMatrixConvolutionImageFilter::kMax_TileMode - 1);
662         bool convolveAlpha = make_bool();
663         SkScalar gain, bias;
664         fuzz->next(&gain, &bias);
665         sk_sp<SkImageFilter> fil = make_image_filter();
666         filter = SkMatrixConvolutionImageFilter::Make(size,
667                                                       kernel.begin(),
668                                                       gain,
669                                                       bias,
670                                                       kernelOffset,
671                                                       (SkMatrixConvolutionImageFilter::TileMode)mode,
672                                                       convolveAlpha,
673                                                       fil,
674                                                       &cropR);
675         break;
676     }
677     case COMPOSE: {
678         sk_sp<SkImageFilter> filA = make_image_filter();
679         sk_sp<SkImageFilter> filB = make_image_filter();
680         filter = SkComposeImageFilter::Make(filA, filB);
681         break;
682     }
683     case DISTANT_LIGHT: {
684         SkPoint3 p = make_point();
685         SkColor c = make_color();
686         SkScalar ss, kd;
687         fuzz->next(&ss, &kd);
688         int shininess;
689         fuzz->nextRange(&shininess, 0, 9);
690         sk_sp<SkImageFilter> fil = make_image_filter();
691         filter = make_bool()
692                  ? SkLightingImageFilter::MakeDistantLitDiffuse(p, c, ss, kd, fil)
693                  : SkLightingImageFilter::MakeDistantLitSpecular(p, c, ss, kd, shininess, fil);
694         break;
695     }
696     case POINT_LIGHT: {
697         SkPoint3 p = make_point();
698         SkColor c = make_color();
699         SkScalar ss, kd;
700         fuzz->next(&ss, &kd);
701         int shininess;
702         fuzz->nextRange(&shininess, 0, 9);
703         sk_sp<SkImageFilter> fil = make_image_filter();
704         filter = make_bool()
705                  ? SkLightingImageFilter::MakePointLitDiffuse(p, c, ss, kd, fil)
706                  : SkLightingImageFilter::MakePointLitSpecular(p, c, ss, kd, shininess, fil);
707         break;
708     }
709     case SPOT_LIGHT: {
710         SkPoint3 p = make_point();
711         SkColor c = make_color();
712         SkScalar se, ca, ss, kd;
713         fuzz->next(&se, &ca, &ss, &kd);
714         int shininess;
715         fuzz->nextRange(&shininess, 0, 9);
716         sk_sp<SkImageFilter> fil = make_image_filter();
717         filter = make_bool()
718                  ? SkLightingImageFilter::MakeSpotLitDiffuse(SkPoint3::Make(0, 0, 0),
719                                                              p, se, ca, c, ss, kd, fil)
720                  : SkLightingImageFilter::MakeSpotLitSpecular(SkPoint3::Make(0, 0, 0),
721                                                               p, se, ca, c, ss, kd,
722                                                               shininess, fil);
723         break;
724     }
725     case NOISE: {
726         SkScalar bfx = make_number(true);
727         SkScalar bfy = make_number(true);
728         SkScalar seed = make_number(false);
729         int octaves;
730         fuzz->nextRange(&octaves, 0, 9);
731         sk_sp<SkShader> shader(make_bool()
732                 ? SkPerlinNoiseShader::MakeFractalNoise(bfx, bfy, octaves, seed)
733                 : SkPerlinNoiseShader::MakeTurbulence(bfx, bfy, octaves, seed));
734         SkPaint paint;
735         paint.setShader(shader);
736         SkImageFilter::CropRect cropR(SkRect::MakeWH(SkIntToScalar(kBitmapSize),
737                                                      SkIntToScalar(kBitmapSize)));
738         filter = SkPaintImageFilter::Make(paint, &cropR);
739         break;
740     }
741     case DROP_SHADOW: {
742         SkScalar dx, dy, sx, sy;
743         fuzz->next(&dx, &dy);
744         sx = make_number(true);
745         sy = make_number(true);
746         SkColor c = make_color();
747         SkDropShadowImageFilter::ShadowMode mode = make_shadow_mode();
748         sk_sp<SkImageFilter> fil = make_image_filter();
749         filter = SkDropShadowImageFilter::Make(dx, dy, sx, sy, c, mode, fil, nullptr);
750         break;
751     }
752     case MORPHOLOGY: {
753         int rx, ry;
754         fuzz->nextRange(&rx, 0, kBitmapSize);
755         fuzz->nextRange(&ry, 0, kBitmapSize);
756         sk_sp<SkImageFilter> fil = make_image_filter();
757         if (make_bool()) {
758             filter = SkDilateImageFilter::Make(rx, ry, fil);
759         } else {
760             filter = SkErodeImageFilter::Make(rx, ry, fil);
761         }
762         break;
763     }
764     case BITMAP: {
765         sk_sp<SkImage> image(SkImage::MakeFromBitmap(make_bitmap()));
766         if (make_bool()) {
767             filter = SkImageSource::Make(std::move(image),
768                                          make_rect(),
769                                          make_rect(),
770                                          kHigh_SkFilterQuality);
771         } else {
772             filter = SkImageSource::Make(std::move(image));
773         }
774         break;
775     }
776     case DISPLACE: {
777         SkDisplacementMapEffect::ChannelSelectorType x = make_channel_selector_type();
778         SkDisplacementMapEffect::ChannelSelectorType y = make_channel_selector_type();
779         SkScalar scale = make_number(false);
780         sk_sp<SkImageFilter> filA = make_image_filter(false);
781         sk_sp<SkImageFilter> filB = make_image_filter();
782 
783         filter = SkDisplacementMapEffect::Make(x, y, scale, filA, filB);
784         break;
785     }
786     case TILE: {
787         SkRect src = make_rect();
788         SkRect dest = make_rect();
789         sk_sp<SkImageFilter> fil = make_image_filter(false);
790         filter = SkTileImageFilter::Make(src, dest, fil);
791         break;
792     }
793     case PICTURE: {
794         SkRTreeFactory factory;
795         SkPictureRecorder recorder;
796         SkCanvas* recordingCanvas = recorder.beginRecording(SkIntToScalar(kBitmapSize),
797                                                             SkIntToScalar(kBitmapSize),
798                                                             &factory, 0);
799         drawSomething(recordingCanvas);
800         sk_sp<SkPicture> pict(recorder.finishRecordingAsPicture());
801         filter = SkPictureImageFilter::Make(pict, make_rect());
802         break;
803     }
804     case PAINT: {
805         SkImageFilter::CropRect cropR(make_rect());
806         filter = SkPaintImageFilter::Make(make_paint(), &cropR);
807         break;
808     }
809     default:
810         break;
811     }
812     return filter;
813 }
814 
make_serialized_image_filter()815 static sk_sp<SkImageFilter> make_serialized_image_filter() {
816     sk_sp<SkImageFilter> filter(make_image_filter(false));
817     sk_sp<SkData> data(SkValidatingSerializeFlattenable(filter.get()));
818     const unsigned char* ptr = static_cast<const unsigned char*>(data->data());
819     size_t len = data->size();
820 #ifdef SK_ADD_RANDOM_BIT_FLIPS
821     unsigned char* p = const_cast<unsigned char*>(ptr);
822     for (size_t i = 0; i < len; ++i, ++p) {
823         uint8_t j;
824         fuzz->nextRange(&j, 1, 250);
825         if (j == 1) { // 0.4% of the time, flip a bit or byte
826             uint8_t k;
827             fuzz->nextRange(&k, 1, 10);
828             if (k == 1) { // Then 10% of the time, change a whole byte
829                 uint8_t s;
830                 fuzz->nextRange(&s, 0, 2);
831                 switch(s) {
832                 case 0:
833                     *p ^= 0xFF; // Flip entire byte
834                     break;
835                 case 1:
836                     *p = 0xFF; // Set all bits to 1
837                     break;
838                 case 2:
839                     *p = 0x00; // Set all bits to 0
840                     break;
841                 }
842             } else {
843                 uint8_t s;
844                 fuzz->nextRange(&s, 0, 7);
845                 *p ^= (1 << 7);
846             }
847         }
848     }
849 #endif // SK_ADD_RANDOM_BIT_FLIPS
850     return SkValidatingDeserializeImageFilter(ptr, len);
851 }
852 
drawClippedBitmap(SkCanvas * canvas,int x,int y,const SkPaint & paint)853 static void drawClippedBitmap(SkCanvas* canvas, int x, int y, const SkPaint& paint) {
854     canvas->save();
855     canvas->clipRect(SkRect::MakeXYWH(SkIntToScalar(x), SkIntToScalar(y),
856         SkIntToScalar(kBitmapSize), SkIntToScalar(kBitmapSize)));
857     canvas->drawBitmap(make_bitmap(), SkIntToScalar(x), SkIntToScalar(y), &paint);
858     canvas->restore();
859 }
860 
DEF_FUZZ(SerializedImageFilter,f)861 DEF_FUZZ(SerializedImageFilter, f) {
862     fuzz = f;
863 
864     SkPaint paint;
865     paint.setImageFilter(make_serialized_image_filter());
866     SkBitmap bitmap;
867     SkCanvas canvas(bitmap);
868     drawClippedBitmap(&canvas, 0, 0, paint);
869 }
870