Index: fuzz/FuzzGradients.cpp |
diff --git a/fuzz/FuzzGradients.cpp b/fuzz/FuzzGradients.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d24bdbe0579a1a4fba23559bb2b39679945c3bd4 |
--- /dev/null |
+++ b/fuzz/FuzzGradients.cpp |
@@ -0,0 +1,294 @@ |
+/* |
+ * Copyright 2016 Google Inc. |
+ * |
+ * Use of this source code is governed by a BSD-style license that can be |
+ * found in the LICENSE file. |
+ */ |
+ |
+#include "Fuzz.h" |
+#include "SkCanvas.h" |
+#include "SkGradientShader.h" |
+#include "SkSurface.h" |
+#include "SkTLazy.h" |
+ |
+#include <algorithm> |
+ |
+const int MAX_COUNT = 400; |
+ |
+bool makeMatrix(Fuzz* fuzz, SkMatrix* m) { |
+ SkScalar scaleX, skewX, transX, skewY, scaleY, transY, persp0, persp1, persp2; |
+ if (!fuzz->next<SkScalar>(&scaleX) || |
+ !fuzz->next<SkScalar>(&skewX) || |
+ !fuzz->next<SkScalar>(&transX) || |
+ !fuzz->next<SkScalar>(&skewY) || |
+ !fuzz->next<SkScalar>(&scaleY) || |
+ !fuzz->next<SkScalar>(&transY) || |
+ !fuzz->next<SkScalar>(&persp0) || |
+ !fuzz->next<SkScalar>(&persp1) || |
+ !fuzz->next<SkScalar>(&persp2)) { |
+ return false; |
+ } |
+ m->setAll(scaleX, skewX, transX, skewY, scaleY, transY, persp0, persp1, persp2); |
+ return true; |
+} |
+ |
+bool initGradientParams(Fuzz* fuzz, uint32_t* count, SkColor** colors, SkScalar** pos, |
+ SkShader::TileMode* mode) { |
+ if (fuzz->remaining() < sizeof(uint32_t)) { |
+ return false; |
+ } |
+ uint32_t t_count; |
+ SkColor* t_colors; |
+ SkScalar* t_pos; |
+ |
+ t_count = fuzz->nextRangeU(0, MAX_COUNT); |
+ if (t_count == 1) { |
+ t_count = 2; |
+ } |
+ |
+ if (fuzz->remaining() < (1 + t_count * (sizeof(SkColor) + sizeof(SkScalar)))) { |
+ return false; |
+ } |
+ t_colors = new SkColor[t_count]; |
+ t_pos = new SkScalar[t_count]; |
+ for (uint32_t i = 0; i < t_count; i++) { |
+ fuzz->next<SkColor>(&t_colors[i]); |
+ fuzz->next<SkScalar>(&t_pos[i]); |
+ } |
+ |
+ if (t_count == 0) { |
+ *count = 0; |
+ *colors = NULL; |
+ *pos = NULL; |
+ } else { |
+ std::sort(t_pos, t_pos + t_count); |
+ t_pos[0] = 0; |
+ t_pos[t_count - 1] = 1; |
+ *count = t_count; |
+ *colors = t_colors; |
+ *pos = t_pos; |
+ } |
+ |
+ *mode = static_cast<SkShader::TileMode>(fuzz->nextRangeU(0, 3)); |
+ return true; |
+} |
+ |
+void fuzzLinearGradient(Fuzz* fuzz) { |
+ SkScalar a, b, c, d; |
+ bool useLocalMatrix, useGlobalMatrix; |
+ if (!fuzz->next<SkScalar>(&a) || |
+ !fuzz->next<SkScalar>(&b) || |
+ !fuzz->next<SkScalar>(&c) || |
+ !fuzz->next<SkScalar>(&d) || |
+ !fuzz->next<bool>(&useLocalMatrix) || |
+ !fuzz->next<bool>(&useGlobalMatrix)) { |
+ return; |
+ } |
+ SkPoint pts[2] = {SkPoint::Make(a,b), SkPoint::Make(c, d)}; |
+ |
+ uint32_t count; |
+ SkColor* colors; |
+ SkScalar* pos; |
+ SkShader::TileMode mode; |
+ if (!initGradientParams(fuzz, &count, &colors, &pos, &mode)) { |
+ return; |
+ } |
+ |
+ SkPaint p; |
+ uint32_t flags; |
+ if (!fuzz->next(&flags)) { |
+ return; |
+ } |
+ |
+ SkTLazy<SkMatrix> localMatrix; |
+ if (useLocalMatrix && !makeMatrix(fuzz, localMatrix.init())) { |
+ return; |
+ } |
+ p.setShader(SkGradientShader::MakeLinear(pts, colors, pos, count, mode, |
+ flags, localMatrix.getMaybeNull())); |
+ |
+ sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50)); |
+ if (useGlobalMatrix) { |
+ SkMatrix gm; |
+ if (!makeMatrix(fuzz, &gm)) { |
+ return; |
+ } |
+ SkCanvas* c = surface->getCanvas(); |
+ c->setMatrix(gm); |
+ c->drawPaint(p); |
+ } else { |
+ surface->getCanvas()->drawPaint(p); |
+ } |
+} |
+ |
+void fuzzRadialGradient(Fuzz* fuzz) { |
+ SkScalar a, b, radius; |
+ bool useLocalMatrix, useGlobalMatrix; |
+ if (!fuzz->next<SkScalar>(&a) || |
+ !fuzz->next<SkScalar>(&b) || |
+ !fuzz->next<SkScalar>(&radius) || |
+ !fuzz->next<bool>(&useLocalMatrix) || |
+ !fuzz->next<bool>(&useGlobalMatrix)) { |
+ return; |
+ } |
+ SkPoint center = SkPoint::Make(a,b); |
+ |
+ uint32_t count; |
+ SkColor* colors; |
+ SkScalar* pos; |
+ SkShader::TileMode mode; |
+ if (!initGradientParams(fuzz, &count, &colors, &pos, &mode)) { |
+ return; |
+ } |
+ |
+ SkPaint p; |
+ uint32_t flags; |
+ if (!fuzz->next(&flags)) { |
+ return; |
+ } |
+ |
+ SkTLazy<SkMatrix> localMatrix; |
+ if (useLocalMatrix && !makeMatrix(fuzz, localMatrix.init())) { |
+ return; |
+ } |
+ p.setShader(SkGradientShader::MakeRadial(center, radius, colors, pos, |
+ count, mode, flags, localMatrix.getMaybeNull())); |
+ |
+ |
+ sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50)); |
+ if (useGlobalMatrix) { |
+ SkMatrix gm; |
+ if (!makeMatrix(fuzz, &gm)) { |
+ return; |
+ } |
+ SkCanvas* c = surface->getCanvas(); |
+ c->setMatrix(gm); |
+ c->drawPaint(p); |
+ } else { |
+ surface->getCanvas()->drawPaint(p); |
+ } |
+} |
+ |
+void fuzzTwoPointConicalGradient(Fuzz* fuzz) { |
+ SkScalar a, b, startRadius, c, d, endRadius; |
+ bool useLocalMatrix, useGlobalMatrix; |
+ if (!fuzz->next<SkScalar>(&a) || |
+ !fuzz->next<SkScalar>(&b) || |
+ !fuzz->next<SkScalar>(&startRadius) || |
+ !fuzz->next<SkScalar>(&c) || |
+ !fuzz->next<SkScalar>(&d) || |
+ !fuzz->next<SkScalar>(&endRadius) || |
+ !fuzz->next<bool>(&useLocalMatrix) || |
+ !fuzz->next<bool>(&useGlobalMatrix)) { |
+ return; |
+ } |
+ SkPoint start = SkPoint::Make(a, b); |
+ SkPoint end = SkPoint::Make(c, d); |
+ |
+ uint32_t count; |
+ SkColor* colors; |
+ SkScalar* pos; |
+ SkShader::TileMode mode; |
+ if (!initGradientParams(fuzz, &count, &colors, &pos, &mode)) { |
+ return; |
+ } |
+ |
+ SkPaint p; |
+ uint32_t flags; |
+ if (!fuzz->next(&flags)) { |
+ return; |
+ } |
+ |
+ SkTLazy<SkMatrix> localMatrix; |
+ if (useLocalMatrix && !makeMatrix(fuzz, localMatrix.init())) { |
+ return; |
+ } |
+ p.setShader(SkGradientShader::MakeTwoPointConical(start, startRadius, end, |
+ endRadius, colors, pos, count, mode, flags, localMatrix.getMaybeNull())); |
+ |
+ sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50)); |
+ if (useGlobalMatrix) { |
+ SkMatrix gm; |
+ if (!makeMatrix(fuzz, &gm)) { |
+ return; |
+ } |
+ SkCanvas* c = surface->getCanvas(); |
+ c->setMatrix(gm); |
+ c->drawPaint(p); |
+ } else { |
+ surface->getCanvas()->drawPaint(p); |
+ } |
+} |
+ |
+void fuzzSweepGradient(Fuzz* fuzz) { |
+ SkScalar cx, cy; |
+ bool useLocalMatrix, useGlobalMatrix; |
+ if (!fuzz->next<SkScalar>(&cx) || |
+ !fuzz->next<SkScalar>(&cy) || |
+ !fuzz->next<bool>(&useLocalMatrix) || |
+ !fuzz->next<bool>(&useGlobalMatrix)) { |
+ return; |
+ } |
+ |
+ uint32_t count; |
+ SkColor* colors; |
+ SkScalar* pos; |
+ SkShader::TileMode mode; |
+ if (!initGradientParams(fuzz, &count, &colors, &pos, &mode)) { |
+ return; |
+ } |
+ |
+ SkPaint p; |
+ if (useLocalMatrix) { |
+ SkMatrix m; |
+ if (!makeMatrix(fuzz, &m)) { |
+ return; |
+ } |
+ uint32_t flags; |
+ if (!fuzz->next(&flags)) { |
+ return; |
+ } |
+ p.setShader(SkGradientShader::MakeSweep(cx, cy, colors, pos, count, flags, &m)); |
+ } else { |
+ p.setShader(SkGradientShader::MakeSweep(cx, cy, colors, pos, count)); |
+ } |
+ |
+ |
+ sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50)); |
+ if (useGlobalMatrix) { |
+ SkMatrix gm; |
+ if (!makeMatrix(fuzz, &gm)) { |
+ return; |
+ } |
+ SkCanvas* c = surface->getCanvas(); |
+ c->setMatrix(gm); |
+ c->drawPaint(p); |
+ } else { |
+ surface->getCanvas()->drawPaint(p); |
+ } |
+} |
+ |
+DEF_FUZZ(Gradients, fuzz) { |
+ uint8_t i; |
+ if (!fuzz->next<uint8_t>(&i)) { |
+ return; |
+ } |
+ |
+ switch(i) { |
+ case 0: |
+ SkDebugf("LinearGradient\n"); |
+ fuzzLinearGradient(fuzz); |
+ return; |
+ case 1: |
+ SkDebugf("RadialGradient\n"); |
+ fuzzRadialGradient(fuzz); |
+ return; |
+ case 2: |
+ SkDebugf("TwoPointConicalGradient\n"); |
+ fuzzTwoPointConicalGradient(fuzz); |
+ return; |
+ } |
+ SkDebugf("SweepGradient\n"); |
+ fuzzSweepGradient(fuzz); |
+ return; |
+} |