/*
 * Copyright 2019 Google LLC.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm/gm.h"

#include "include/core/SkCanvas.h"
#include "include/core/SkClipOp.h"
#include "include/core/SkPath.h"
#include "include/core/SkPathBuilder.h"
#include "tools/ToolUtils.h"

#if defined(SK_GANESH)
#include "include/gpu/ganesh/GrContextOptions.h"
#include "include/gpu/ganesh/GrRecordingContext.h"
#include "src/gpu/ganesh/GrDirectContextPriv.h"
#include "src/gpu/ganesh/GrDrawingManager.h"
#include "src/gpu/ganesh/GrRecordingContextPriv.h"
#endif

#if defined(SK_GRAPHITE)
#include "include/gpu/graphite/ContextOptions.h"
#include "src/gpu/graphite/ContextOptionsPriv.h"
#endif

namespace skiagm {

/**
 * This test originally ensured that the ccpr path cache preserved fill rules properly. CCPR is gone
 * now, but we decided to keep the test.
 */
class ManyPathAtlasesGM : public GM {
public:
    ManyPathAtlasesGM(int maxAtlasSize) : fMaxAtlasSize(maxAtlasSize) {}
private:
    SkString getName() const override {
        return SkStringPrintf("manypathatlases_%i", fMaxAtlasSize);
    }
    SkISize getISize() override { return SkISize::Make(128, 128); }

#if defined(SK_GANESH)
    void modifyGrContextOptions(GrContextOptions* ctxOptions) override {
        // This will test the case where the atlas runs out of room if fMaxAtlasSize is small.
        ctxOptions->fMaxTextureAtlasSize = fMaxAtlasSize;
    }
#endif

#if defined(SK_GRAPHITE)
    void modifyGraphiteContextOptions(skgpu::graphite::ContextOptions* options) const override {
        SkASSERT(options->fOptionsPriv);
        options->fOptionsPriv->fMaxTextureAtlasSize = fMaxAtlasSize;
    }
#endif

    void onDraw(SkCanvas* canvas) override {
        canvas->clear(SkColors::kYellow);

#if defined(SK_GANESH)
        // Flush the context to make the DAG empty. This will test the case where we try to add an
        // atlas task to an empty DAG.
        auto dContext = GrAsDirectContext(canvas->recordingContext());
        if (dContext) {
            dContext->flush();
        }
#endif

        SkPath clip = SkPathBuilder().moveTo(-50, 20)
                                     .cubicTo(-50, -20, 50, -20, 50, 40)
                                     .cubicTo(20, 0, -20, 0, -50, 20)
                                     .transform(SkMatrix::Translate(64, 70))
                                     .detach();
        for (int i = 0; i < 4; ++i) {
            SkPath rotatedClip = clip.makeTransform(SkMatrix::RotateDeg(30 * i + 128, {64, 70}));
            rotatedClip.setIsVolatile(true);
            canvas->clipPath(rotatedClip, SkClipOp::kDifference, true);
        }
        SkPath path = SkPathBuilder().moveTo(20, 0)
                                     .lineTo(108, 0).cubicTo(108, 20, 108, 20, 128, 20)
                                     .lineTo(128, 108).cubicTo(108, 108, 108, 108, 108, 128)
                                     .lineTo(20, 128).cubicTo(20, 108, 20, 108, 0, 108)
                                     .lineTo(0, 20).cubicTo(20, 20, 20, 20, 20, 0)
                                     .detach();
        path.setIsVolatile(true);
        SkPaint teal;
        teal.setColor4f({.03f, .91f, .87f, 1});
        teal.setAntiAlias(true);
        canvas->drawPath(path, teal);
    }

    const int fMaxAtlasSize;
};

DEF_GM( return new ManyPathAtlasesGM(128); )  // Atlas runs out of room.
DEF_GM( return new ManyPathAtlasesGM(2048); )  // Atlas does not run out of room.

}  // namespace skiagm
