static void fuzz_canvas()

in fuzz/FuzzCanvas.cpp [994:1498]


static void fuzz_canvas(Fuzz* fuzz, SkCanvas* canvas, int depth = 9) {
    if (!fuzz || !canvas || depth <= 0) {
        return;
    }
    SkAutoCanvasRestore autoCanvasRestore(canvas, false);
    unsigned N;
    fuzz->nextRange(&N, 0, 2000);
    for (unsigned loop = 0; loop < N; ++loop) {
        if (fuzz->exhausted()) {
            return;
        }
        SkPaint paint;
        SkFont font = ToolUtils::DefaultFont();
        unsigned drawCommand;
        fuzz->nextRange(&drawCommand, 0, 62);
        switch (drawCommand) {
            case 0:
#if defined(SK_GANESH)
                if (auto dContext = GrAsDirectContext(canvas->recordingContext())) {
                    dContext->flushAndSubmit();
                }
#endif
                break;
            case 1:
                canvas->save();
                break;
            case 2: {
                SkRect bounds;
                fuzz->next(&bounds);
                fuzz_paint(fuzz, &paint, depth - 1);
                canvas->saveLayer(&bounds, &paint);
                break;
            }
            case 3: {
                SkRect bounds;
                fuzz->next(&bounds);
                canvas->saveLayer(&bounds, nullptr);
                break;
            }
            case 4:
                fuzz_paint(fuzz, &paint, depth - 1);
                canvas->saveLayer(nullptr, &paint);
                break;
            case 5:
                canvas->saveLayer(nullptr, nullptr);
                break;
            case 6: {
                uint8_t alpha;
                fuzz->next(&alpha);
                canvas->saveLayerAlpha(nullptr, (U8CPU)alpha);
                break;
            }
            case 7: {
                SkRect bounds;
                uint8_t alpha;
                fuzz->next(&bounds, &alpha);
                canvas->saveLayerAlpha(&bounds, (U8CPU)alpha);
                break;
            }
            case 8: {
                SkCanvas::SaveLayerRec saveLayerRec;
                SkRect bounds;
                if (make_fuzz_t<bool>(fuzz)) {
                    fuzz->next(&bounds);
                    saveLayerRec.fBounds = &bounds;
                }
                if (make_fuzz_t<bool>(fuzz)) {
                    fuzz_paint(fuzz, &paint, depth - 1);
                    saveLayerRec.fPaint = &paint;
                }
                sk_sp<SkImageFilter> imageFilter;
                if (make_fuzz_t<bool>(fuzz)) {
                    imageFilter = make_fuzz_imageFilter(fuzz, depth - 1);
                    saveLayerRec.fBackdrop = imageFilter.get();
                }
                // _DumpCanvas can't handle this.
                // if (make_fuzz_t<bool>(fuzz)) {
                //     saveLayerRec.fSaveLayerFlags |= SkCanvas::kPreserveLCDText_SaveLayerFlag;
                // }

                canvas->saveLayer(saveLayerRec);
                break;
            }
            case 9:
                canvas->restore();
                break;
            case 10: {
                int saveCount;
                fuzz->next(&saveCount);
                canvas->restoreToCount(saveCount);
                break;
            }
            case 11: {
                SkScalar x, y;
                fuzz->next(&x, &y);
                canvas->translate(x, y);
                break;
            }
            case 12: {
                SkScalar x, y;
                fuzz->next(&x, &y);
                canvas->scale(x, y);
                break;
            }
            case 13: {
                SkScalar v;
                fuzz->next(&v);
                canvas->rotate(v);
                break;
            }
            case 14: {
                SkScalar x, y, v;
                fuzz->next(&x, &y, &v);
                canvas->rotate(v, x, y);
                break;
            }
            case 15: {
                SkScalar x, y;
                fuzz->next(&x, &y);
                canvas->skew(x, y);
                break;
            }
            case 16: {
                SkMatrix mat;
                FuzzNiceMatrix(fuzz, &mat);
                canvas->concat(mat);
                break;
            }
            case 17: {
                SkMatrix mat;
                FuzzNiceMatrix(fuzz, &mat);
                canvas->setMatrix(mat);
                break;
            }
            case 18:
                canvas->resetMatrix();
                break;
            case 19: {
                SkRect r;
                int op;
                bool doAntiAlias;
                fuzz->next(&r, &doAntiAlias);
                fuzz->nextRange(&op, 0, 1);
                r.sort();
                canvas->clipRect(r, (SkClipOp)op, doAntiAlias);
                break;
            }
            case 20: {
                SkRRect rr;
                int op;
                bool doAntiAlias;
                FuzzNiceRRect(fuzz, &rr);
                fuzz->next(&doAntiAlias);
                fuzz->nextRange(&op, 0, 1);
                canvas->clipRRect(rr, (SkClipOp)op, doAntiAlias);
                break;
            }
            case 21: {
                SkPath path;
                FuzzNicePath(fuzz, &path, 30);
                int op;
                bool doAntiAlias;
                fuzz->next(&doAntiAlias);
                fuzz->nextRange(&op, 0, 1);
                canvas->clipPath(path, (SkClipOp)op, doAntiAlias);
                break;
            }
            case 22: {
                SkRegion region;
                int op;
                fuzz->next(&region);
                fuzz->nextRange(&op, 0, 1);
                canvas->clipRegion(region, (SkClipOp)op);
                break;
            }
            case 23:
                fuzz_paint(fuzz, &paint, depth - 1);
                canvas->drawPaint(paint);
                break;
            case 24: {
                fuzz_paint(fuzz, &paint, depth - 1);
                SkCanvas::PointMode pointMode;
                fuzz->nextRange(&pointMode,
                                SkCanvas::kPoints_PointMode, SkCanvas::kPolygon_PointMode);
                size_t count;
                constexpr int kMaxCount = 30;
                fuzz->nextRange(&count, 0, kMaxCount);
                SkPoint pts[kMaxCount];
                fuzz->nextN(pts, count);
                canvas->drawPoints(pointMode, count, pts, paint);
                break;
            }
            case 25: {
                fuzz_paint(fuzz, &paint, depth - 1);
                SkRect r;
                fuzz->next(&r);
                if (!r.isFinite()) {
                    break;
                }
                canvas->drawRect(r, paint);
                break;
            }
            case 26: {
                fuzz_paint(fuzz, &paint, depth - 1);
                SkRegion region;
                fuzz->next(&region);
                canvas->drawRegion(region, paint);
                break;
            }
            case 27: {
                fuzz_paint(fuzz, &paint, depth - 1);
                SkRect r;
                fuzz->next(&r);
                if (!r.isFinite()) {
                    break;
                }
                canvas->drawOval(r, paint);
                break;
            }
            case 28: break; // must have deleted this some time earlier
            case 29: {
                fuzz_paint(fuzz, &paint, depth - 1);
                SkRRect rr;
                FuzzNiceRRect(fuzz, &rr);
                canvas->drawRRect(rr, paint);
                break;
            }
            case 30: {
                fuzz_paint(fuzz, &paint, depth - 1);
                SkRRect orr, irr;
                FuzzNiceRRect(fuzz, &orr);
                FuzzNiceRRect(fuzz, &irr);
                if (orr.getBounds().contains(irr.getBounds())) {
                    canvas->drawDRRect(orr, irr, paint);
                }
                break;
            }
            case 31: {
                fuzz_paint(fuzz, &paint, depth - 1);
                SkRect r;
                SkScalar start, sweep;
                bool useCenter;
                fuzz->next(&r, &start, &sweep, &useCenter);
                canvas->drawArc(r, start, sweep, useCenter, paint);
                break;
            }
            case 32: {
                fuzz_paint(fuzz, &paint, depth - 1);
                SkPath path;
                FuzzNicePath(fuzz, &path, 60);
                canvas->drawPath(path, paint);
                break;
            }
            case 33: {
                sk_sp<SkImage> img = make_fuzz_image(fuzz);
                SkScalar left, top;
                bool usePaint;
                fuzz->next(&left, &top, &usePaint);
                if (usePaint) {
                    fuzz_paint(fuzz, &paint, depth - 1);
                }
                canvas->drawImage(img.get(), left, top, SkSamplingOptions(),
                                  usePaint ? &paint : nullptr);
                break;
            }
            case 35: {
                auto img = make_fuzz_image(fuzz);
                SkIRect src;
                SkRect dst;
                bool usePaint;
                fuzz->next(&src, &dst, &usePaint);
                if (usePaint) {
                    fuzz_paint(fuzz, &paint, depth - 1);
                }
                SkCanvas::SrcRectConstraint constraint =
                        make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
                                                : SkCanvas::kFast_SrcRectConstraint;
                canvas->drawImageRect(img.get(), SkRect::Make(src), dst, SkSamplingOptions(),
                                      usePaint ? &paint : nullptr, constraint);
                break;
            }
            case 37: {
                auto img = make_fuzz_image(fuzz);
                SkIRect center;
                SkRect dst;
                bool usePaint;
                fuzz->next(&usePaint);
                if (usePaint) {
                    fuzz_paint(fuzz, &paint, depth - 1);
                }
                if (make_fuzz_t<bool>(fuzz)) {
                    fuzz->next(&center);
                } else {  // Make valid center, see SkLatticeIter::Valid().
                    fuzz->nextRange(&center.fLeft, 0, img->width() - 1);
                    fuzz->nextRange(&center.fTop, 0, img->height() - 1);
                    fuzz->nextRange(&center.fRight, center.fLeft + 1, img->width());
                    fuzz->nextRange(&center.fBottom, center.fTop + 1, img->height());
                }
                fuzz->next(&dst);
                canvas->drawImageNine(img.get(), center, dst, SkFilterMode::kNearest,
                                      usePaint ? &paint : nullptr);
                break;
            }
            case 44: {
                auto img = make_fuzz_image(fuzz);
                bool usePaint;
                SkRect dst;
                fuzz->next(&usePaint, &dst);
                if (usePaint) {
                    fuzz_paint(fuzz, &paint, depth - 1);
                }
                constexpr int kMax = 6;
                int xDivs[kMax], yDivs[kMax];
                SkCanvas::Lattice lattice{xDivs, yDivs, nullptr, 0, 0, nullptr, nullptr};
                fuzz->nextRange(&lattice.fXCount, 2, kMax);
                fuzz->nextRange(&lattice.fYCount, 2, kMax);
                fuzz->nextN(xDivs, lattice.fXCount);
                fuzz->nextN(yDivs, lattice.fYCount);
                canvas->drawImageLattice(img.get(), lattice, dst, SkFilterMode::kLinear,
                                         usePaint ? &paint : nullptr);
                break;
            }
            case 45: {
                fuzz_paint(fuzz, &paint, depth - 1);
                font = fuzz_font(fuzz);
                SkTextEncoding encoding = fuzz_paint_text_encoding(fuzz);
                SkScalar x, y;
                fuzz->next(&x, &y);
                SkTDArray<uint8_t> text = make_fuzz_text(fuzz, font, encoding);
                canvas->drawSimpleText(text.begin(), SkToSizeT(text.size()), encoding, x, y,
                                       font, paint);
                break;
            }
            case 46: {
                // was drawPosText
                break;
            }
            case 47: {
                // was drawPosTextH
                break;
            }
            case 48: {
                // was drawtextonpath
                break;
            }
            case 49: {
                // was drawtextonpath
                break;
            }
            case 50: {
                // was drawTextRSXform
                break;
            }
            case 51: {
                sk_sp<SkTextBlob> blob = make_fuzz_textblob(fuzz);
                fuzz_paint(fuzz, &paint, depth - 1);
                SkScalar x, y;
                fuzz->next(&x, &y);
                canvas->drawTextBlob(blob, x, y, paint);
                break;
            }
            case 52: {
                SkMatrix matrix;
                bool usePaint, useMatrix;
                fuzz->next(&usePaint, &useMatrix);
                if (usePaint) {
                    fuzz_paint(fuzz, &paint, depth - 1);
                }
                if (useMatrix) {
                    FuzzNiceMatrix(fuzz, &matrix);
                }
                auto pic = make_fuzz_picture(fuzz, depth - 1);
                canvas->drawPicture(pic, useMatrix ? &matrix : nullptr,
                                    usePaint ? &paint : nullptr);
                break;
            }
            case 53: {
                fuzz_paint(fuzz, &paint, depth - 1);
                SkVertices::VertexMode vertexMode;
                SkBlendMode blendMode;
                fuzz->nextRange(&vertexMode, 0, SkVertices::kTriangleFan_VertexMode);
                fuzz->nextRange(&blendMode, 0, SkBlendMode::kLastMode);
                constexpr int kMaxCount = 100;
                int vertexCount;
                SkPoint vertices[kMaxCount];
                SkPoint texs[kMaxCount];
                SkColor colors[kMaxCount];
                fuzz->nextRange(&vertexCount, 3, kMaxCount);
                fuzz->nextN(vertices, vertexCount);
                bool useTexs, useColors;
                fuzz->next(&useTexs, &useColors);
                if (useTexs) {
                    fuzz->nextN(texs, vertexCount);
                }
                if (useColors) {
                    fuzz->nextN(colors, vertexCount);
                }
                int indexCount = 0;
                uint16_t indices[kMaxCount * 2];
                if (make_fuzz_t<bool>(fuzz)) {
                    fuzz->nextRange(&indexCount, vertexCount, vertexCount + kMaxCount);
                    for (int index = 0; index < indexCount; ++index) {
                        fuzz->nextRange(&indices[index], 0, vertexCount - 1);
                    }
                }
                canvas->drawVertices(SkVertices::MakeCopy(vertexMode, vertexCount, vertices,
                                                          useTexs ? texs : nullptr,
                                                          useColors ? colors : nullptr,
                                                          indexCount, indices),
                                     blendMode, paint);
                break;
            }
            case 54: {
                SkColor color;
                SkBlendMode blendMode;
                fuzz->nextRange(&blendMode, 0, SkBlendMode::kSrcOver);
                fuzz->next(&color);
                canvas->drawColor(color, blendMode);
                break;
            }
            case 55: {
                SkColor4f color;
                SkBlendMode blendMode;
                float R, G, B, Alpha;
                fuzz->nextRange(&blendMode, 0, SkBlendMode::kSrcOver);
                fuzz->nextRange(&R, -1, 2);
                fuzz->nextRange(&G, -1, 2);
                fuzz->nextRange(&B, -1, 2);
                fuzz->nextRange(&Alpha, 0, 1);
                color = {R, G, B, Alpha};
                canvas->drawColor(color, blendMode);
                break;
            }
            case 56: {
                fuzz_paint(fuzz, &paint, depth - 1);
                SkPoint p0, p1;
                fuzz->next(&p0, &p1);
                canvas->drawLine(p0, p1, paint);
                break;
            }
            case 57: {
                fuzz_paint(fuzz, &paint, depth - 1);
                SkIRect r;
                fuzz->next(&r);
                canvas->drawIRect(r, paint);
                break;
            }
            case 58: {
                fuzz_paint(fuzz, &paint, depth - 1);
                SkScalar radius;
                SkPoint center;
                fuzz->next(&radius, &center);
                canvas->drawCircle(center, radius, paint);
                break;
            }
            case 59: {
                fuzz_paint(fuzz, &paint, depth - 1);
                SkRect oval;
                SkScalar startAngle, sweepAngle;
                bool useCenter;
                fuzz->next(&oval, &startAngle, &sweepAngle, &useCenter);
                canvas->drawArc(oval, startAngle, sweepAngle, useCenter, paint);
                break;
            }
            case 60: {
                fuzz_paint(fuzz, &paint, depth - 1);
                SkRect rect;
                SkScalar rx, ry;
                fuzz->next(&rect, &rx, &ry);
                canvas->drawRoundRect(rect, rx, ry, paint);
                break;
            }
            case 61: {
                fuzz_paint(fuzz, &paint, depth - 1);
                font = fuzz_font(fuzz);
                std::string str = make_fuzz_string(fuzz);
                SkScalar x, y;
                fuzz->next(&x, &y);
                canvas->drawString(str.c_str(), x, y, font, paint);
                break;
            }
            case 62: {
                fuzz_paint(fuzz, &paint, depth - 1);
                SkPoint cubics[12];
                SkColor colors[4];
                SkPoint texCoords[4];
                bool useTexCoords;
                fuzz->nextN(cubics, 12);
                fuzz->nextN(colors, 4);
                fuzz->next(&useTexCoords);
                if (useTexCoords) {
                    fuzz->nextN(texCoords, 4);
                }
                SkBlendMode mode;
                fuzz->nextEnum(&mode, SkBlendMode::kLastMode);
                canvas->drawPatch(cubics, colors, useTexCoords ? texCoords : nullptr
                    , mode, paint);
                break;
            }
            default:
                SkASSERT(false);
                break;
        }
    }
}